stringio 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of stringio might be problematic. Click here for more details.
- checksums.yaml +7 -0
- data/README.md +10 -0
- data/depend +17 -0
- data/extconf.rb +3 -0
- data/stringio.c +1730 -0
- metadata +63 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 9593fa26bcf926ea907d5e261a5fe847c2d5ec28f114344e9698adc877a70bd8
|
4
|
+
data.tar.gz: 334c3def4bbbb508503fcd2956e8d084a6183ba4c3a9d0680012c1b905950c1e
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: a2b7616e5b07ed4eef3637a3d4ebee48e5eca030927803bf7d60c80084061de42150cf3df930a90fe45eac2b5ee29a62dce8938b7d34d96c601083c5ed2dbb14
|
7
|
+
data.tar.gz: 44a4c20f3c58e437d79724330ac023d4ccbd383900296c76a4687fc1cd641d1b0845203d55b0e5bfcbc75d884b38d8e7cd4ce102732183353d338aea8012eb70
|
data/README.md
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
# StringIO
|
2
|
+
|
3
|
+
Pseudo `IO` class from/to `String`.
|
4
|
+
|
5
|
+
This library is based on MoonWolf version written in Ruby. Thanks a lot.
|
6
|
+
|
7
|
+
## Differences to `IO`
|
8
|
+
|
9
|
+
* `fileno` raises `NotImplementedError`.
|
10
|
+
* encoding conversion is not implemented, and ignored silently.
|
data/depend
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
# AUTOGENERATED DEPENDENCIES START
|
2
|
+
stringio.o: $(RUBY_EXTCONF_H)
|
3
|
+
stringio.o: $(arch_hdrdir)/ruby/config.h
|
4
|
+
stringio.o: $(hdrdir)/ruby/backward.h
|
5
|
+
stringio.o: $(hdrdir)/ruby/defines.h
|
6
|
+
stringio.o: $(hdrdir)/ruby/encoding.h
|
7
|
+
stringio.o: $(hdrdir)/ruby/intern.h
|
8
|
+
stringio.o: $(hdrdir)/ruby/io.h
|
9
|
+
stringio.o: $(hdrdir)/ruby/missing.h
|
10
|
+
stringio.o: $(hdrdir)/ruby/onigmo.h
|
11
|
+
stringio.o: $(hdrdir)/ruby/oniguruma.h
|
12
|
+
stringio.o: $(hdrdir)/ruby/ruby.h
|
13
|
+
stringio.o: $(hdrdir)/ruby/st.h
|
14
|
+
stringio.o: $(hdrdir)/ruby/subst.h
|
15
|
+
stringio.o: $(top_srcdir)/include/ruby.h
|
16
|
+
stringio.o: stringio.c
|
17
|
+
# AUTOGENERATED DEPENDENCIES END
|
data/extconf.rb
ADDED
data/stringio.c
ADDED
@@ -0,0 +1,1730 @@
|
|
1
|
+
/**********************************************************************
|
2
|
+
|
3
|
+
stringio.c -
|
4
|
+
|
5
|
+
$Author$
|
6
|
+
$RoughId: stringio.c,v 1.13 2002/03/14 03:24:18 nobu Exp $
|
7
|
+
created at: Tue Feb 19 04:10:38 JST 2002
|
8
|
+
|
9
|
+
All the files in this distribution are covered under the Ruby's
|
10
|
+
license (see the file COPYING).
|
11
|
+
|
12
|
+
**********************************************************************/
|
13
|
+
|
14
|
+
#include "ruby.h"
|
15
|
+
#include "ruby/io.h"
|
16
|
+
#include "ruby/encoding.h"
|
17
|
+
#if defined(HAVE_FCNTL_H) || defined(_WIN32)
|
18
|
+
#include <fcntl.h>
|
19
|
+
#elif defined(HAVE_SYS_FCNTL_H)
|
20
|
+
#include <sys/fcntl.h>
|
21
|
+
#endif
|
22
|
+
|
23
|
+
#ifndef RB_INTEGER_TYPE_P
|
24
|
+
# define RB_INTEGER_TYPE_P(c) (FIXNUM_P(c) || RB_TYPE_P(c, T_BIGNUM))
|
25
|
+
#endif
|
26
|
+
|
27
|
+
struct StringIO {
|
28
|
+
VALUE string;
|
29
|
+
rb_encoding *enc;
|
30
|
+
long pos;
|
31
|
+
long lineno;
|
32
|
+
int flags;
|
33
|
+
int count;
|
34
|
+
};
|
35
|
+
|
36
|
+
static VALUE strio_init(int, VALUE *, struct StringIO *, VALUE);
|
37
|
+
static VALUE strio_unget_bytes(struct StringIO *, const char *, long);
|
38
|
+
static long strio_write(VALUE self, VALUE str);
|
39
|
+
|
40
|
+
#define IS_STRIO(obj) (rb_typeddata_is_kind_of((obj), &strio_data_type))
|
41
|
+
#define error_inval(msg) (rb_syserr_fail(EINVAL, msg))
|
42
|
+
#define get_enc(ptr) ((ptr)->enc ? (ptr)->enc : rb_enc_get((ptr)->string))
|
43
|
+
|
44
|
+
static struct StringIO *
|
45
|
+
strio_alloc(void)
|
46
|
+
{
|
47
|
+
struct StringIO *ptr = ALLOC(struct StringIO);
|
48
|
+
ptr->string = Qnil;
|
49
|
+
ptr->pos = 0;
|
50
|
+
ptr->lineno = 0;
|
51
|
+
ptr->flags = 0;
|
52
|
+
ptr->count = 1;
|
53
|
+
return ptr;
|
54
|
+
}
|
55
|
+
|
56
|
+
static void
|
57
|
+
strio_mark(void *p)
|
58
|
+
{
|
59
|
+
struct StringIO *ptr = p;
|
60
|
+
|
61
|
+
rb_gc_mark(ptr->string);
|
62
|
+
}
|
63
|
+
|
64
|
+
static void
|
65
|
+
strio_free(void *p)
|
66
|
+
{
|
67
|
+
struct StringIO *ptr = p;
|
68
|
+
if (--ptr->count <= 0) {
|
69
|
+
xfree(ptr);
|
70
|
+
}
|
71
|
+
}
|
72
|
+
|
73
|
+
static size_t
|
74
|
+
strio_memsize(const void *p)
|
75
|
+
{
|
76
|
+
return sizeof(struct StringIO);
|
77
|
+
}
|
78
|
+
|
79
|
+
static const rb_data_type_t strio_data_type = {
|
80
|
+
"strio",
|
81
|
+
{
|
82
|
+
strio_mark,
|
83
|
+
strio_free,
|
84
|
+
strio_memsize,
|
85
|
+
},
|
86
|
+
0, 0, RUBY_TYPED_FREE_IMMEDIATELY
|
87
|
+
};
|
88
|
+
|
89
|
+
#define check_strio(self) ((struct StringIO*)rb_check_typeddata((self), &strio_data_type))
|
90
|
+
|
91
|
+
static struct StringIO*
|
92
|
+
get_strio(VALUE self)
|
93
|
+
{
|
94
|
+
struct StringIO *ptr = check_strio(rb_io_taint_check(self));
|
95
|
+
|
96
|
+
if (!ptr) {
|
97
|
+
rb_raise(rb_eIOError, "uninitialized stream");
|
98
|
+
}
|
99
|
+
return ptr;
|
100
|
+
}
|
101
|
+
|
102
|
+
static VALUE
|
103
|
+
enc_subseq(VALUE str, long pos, long len, rb_encoding *enc)
|
104
|
+
{
|
105
|
+
str = rb_str_subseq(str, pos, len);
|
106
|
+
rb_enc_associate(str, enc);
|
107
|
+
return str;
|
108
|
+
}
|
109
|
+
|
110
|
+
static VALUE
|
111
|
+
strio_substr(struct StringIO *ptr, long pos, long len, rb_encoding *enc)
|
112
|
+
{
|
113
|
+
VALUE str = ptr->string;
|
114
|
+
long rlen = RSTRING_LEN(str) - pos;
|
115
|
+
|
116
|
+
if (len > rlen) len = rlen;
|
117
|
+
if (len < 0) len = 0;
|
118
|
+
if (len == 0) return rb_enc_str_new(0, 0, enc);
|
119
|
+
return enc_subseq(str, pos, len, enc);
|
120
|
+
}
|
121
|
+
|
122
|
+
#define StringIO(obj) get_strio(obj)
|
123
|
+
|
124
|
+
#define STRIO_READABLE FL_USER4
|
125
|
+
#define STRIO_WRITABLE FL_USER5
|
126
|
+
#define STRIO_READWRITE (STRIO_READABLE|STRIO_WRITABLE)
|
127
|
+
typedef char strio_flags_check[(STRIO_READABLE/FMODE_READABLE == STRIO_WRITABLE/FMODE_WRITABLE) * 2 - 1];
|
128
|
+
#define STRIO_MODE_SET_P(strio, mode) \
|
129
|
+
((RBASIC(strio)->flags & STRIO_##mode) && \
|
130
|
+
((struct StringIO*)DATA_PTR(strio))->flags & FMODE_##mode)
|
131
|
+
#define CLOSED(strio) (!STRIO_MODE_SET_P(strio, READWRITE))
|
132
|
+
#define READABLE(strio) STRIO_MODE_SET_P(strio, READABLE)
|
133
|
+
#define WRITABLE(strio) STRIO_MODE_SET_P(strio, WRITABLE)
|
134
|
+
|
135
|
+
static VALUE sym_exception;
|
136
|
+
|
137
|
+
static struct StringIO*
|
138
|
+
readable(VALUE strio)
|
139
|
+
{
|
140
|
+
struct StringIO *ptr = StringIO(strio);
|
141
|
+
if (!READABLE(strio)) {
|
142
|
+
rb_raise(rb_eIOError, "not opened for reading");
|
143
|
+
}
|
144
|
+
return ptr;
|
145
|
+
}
|
146
|
+
|
147
|
+
static struct StringIO*
|
148
|
+
writable(VALUE strio)
|
149
|
+
{
|
150
|
+
struct StringIO *ptr = StringIO(strio);
|
151
|
+
if (!WRITABLE(strio)) {
|
152
|
+
rb_raise(rb_eIOError, "not opened for writing");
|
153
|
+
}
|
154
|
+
return ptr;
|
155
|
+
}
|
156
|
+
|
157
|
+
static void
|
158
|
+
check_modifiable(struct StringIO *ptr)
|
159
|
+
{
|
160
|
+
if (OBJ_FROZEN(ptr->string)) {
|
161
|
+
rb_raise(rb_eIOError, "not modifiable string");
|
162
|
+
}
|
163
|
+
}
|
164
|
+
|
165
|
+
static VALUE
|
166
|
+
strio_s_allocate(VALUE klass)
|
167
|
+
{
|
168
|
+
return TypedData_Wrap_Struct(klass, &strio_data_type, 0);
|
169
|
+
}
|
170
|
+
|
171
|
+
/*
|
172
|
+
* call-seq: StringIO.new(string=""[, mode])
|
173
|
+
*
|
174
|
+
* Creates new StringIO instance from with _string_ and _mode_.
|
175
|
+
*/
|
176
|
+
static VALUE
|
177
|
+
strio_initialize(int argc, VALUE *argv, VALUE self)
|
178
|
+
{
|
179
|
+
struct StringIO *ptr = check_strio(self);
|
180
|
+
|
181
|
+
if (!ptr) {
|
182
|
+
DATA_PTR(self) = ptr = strio_alloc();
|
183
|
+
}
|
184
|
+
rb_call_super(0, 0);
|
185
|
+
return strio_init(argc, argv, ptr, self);
|
186
|
+
}
|
187
|
+
|
188
|
+
static VALUE
|
189
|
+
strio_init(int argc, VALUE *argv, struct StringIO *ptr, VALUE self)
|
190
|
+
{
|
191
|
+
VALUE string, mode;
|
192
|
+
int trunc = 0;
|
193
|
+
|
194
|
+
switch (rb_scan_args(argc, argv, "02", &string, &mode)) {
|
195
|
+
case 2:
|
196
|
+
if (FIXNUM_P(mode)) {
|
197
|
+
int flags = FIX2INT(mode);
|
198
|
+
ptr->flags = rb_io_oflags_fmode(flags);
|
199
|
+
trunc = flags & O_TRUNC;
|
200
|
+
}
|
201
|
+
else {
|
202
|
+
const char *m = StringValueCStr(mode);
|
203
|
+
ptr->flags = rb_io_modestr_fmode(m);
|
204
|
+
trunc = *m == 'w';
|
205
|
+
}
|
206
|
+
StringValue(string);
|
207
|
+
if ((ptr->flags & FMODE_WRITABLE) && OBJ_FROZEN(string)) {
|
208
|
+
rb_syserr_fail(EACCES, 0);
|
209
|
+
}
|
210
|
+
if (trunc) {
|
211
|
+
rb_str_resize(string, 0);
|
212
|
+
}
|
213
|
+
break;
|
214
|
+
case 1:
|
215
|
+
StringValue(string);
|
216
|
+
ptr->flags = OBJ_FROZEN(string) ? FMODE_READABLE : FMODE_READWRITE;
|
217
|
+
break;
|
218
|
+
case 0:
|
219
|
+
string = rb_enc_str_new("", 0, rb_default_external_encoding());
|
220
|
+
ptr->flags = FMODE_READWRITE;
|
221
|
+
break;
|
222
|
+
}
|
223
|
+
ptr->string = string;
|
224
|
+
ptr->enc = 0;
|
225
|
+
ptr->pos = 0;
|
226
|
+
ptr->lineno = 0;
|
227
|
+
RBASIC(self)->flags |= (ptr->flags & FMODE_READWRITE) * (STRIO_READABLE / FMODE_READABLE);
|
228
|
+
return self;
|
229
|
+
}
|
230
|
+
|
231
|
+
static VALUE
|
232
|
+
strio_finalize(VALUE self)
|
233
|
+
{
|
234
|
+
struct StringIO *ptr = StringIO(self);
|
235
|
+
ptr->string = Qnil;
|
236
|
+
ptr->flags &= ~FMODE_READWRITE;
|
237
|
+
return self;
|
238
|
+
}
|
239
|
+
|
240
|
+
/*
|
241
|
+
* call-seq: StringIO.open(string=""[, mode]) {|strio| ...}
|
242
|
+
*
|
243
|
+
* Equivalent to StringIO.new except that when it is called with a block, it
|
244
|
+
* yields with the new instance and closes it, and returns the result which
|
245
|
+
* returned from the block.
|
246
|
+
*/
|
247
|
+
static VALUE
|
248
|
+
strio_s_open(int argc, VALUE *argv, VALUE klass)
|
249
|
+
{
|
250
|
+
VALUE obj = rb_class_new_instance(argc, argv, klass);
|
251
|
+
if (!rb_block_given_p()) return obj;
|
252
|
+
return rb_ensure(rb_yield, obj, strio_finalize, obj);
|
253
|
+
}
|
254
|
+
|
255
|
+
/* :nodoc: */
|
256
|
+
static VALUE
|
257
|
+
strio_s_new(int argc, VALUE *argv, VALUE klass)
|
258
|
+
{
|
259
|
+
if (rb_block_given_p()) {
|
260
|
+
VALUE cname = rb_obj_as_string(klass);
|
261
|
+
|
262
|
+
rb_warn("%"PRIsVALUE"::new() does not take block; use %"PRIsVALUE"::open() instead",
|
263
|
+
cname, cname);
|
264
|
+
}
|
265
|
+
return rb_class_new_instance(argc, argv, klass);
|
266
|
+
}
|
267
|
+
|
268
|
+
/*
|
269
|
+
* Returns +false+. Just for compatibility to IO.
|
270
|
+
*/
|
271
|
+
static VALUE
|
272
|
+
strio_false(VALUE self)
|
273
|
+
{
|
274
|
+
StringIO(self);
|
275
|
+
return Qfalse;
|
276
|
+
}
|
277
|
+
|
278
|
+
/*
|
279
|
+
* Returns +nil+. Just for compatibility to IO.
|
280
|
+
*/
|
281
|
+
static VALUE
|
282
|
+
strio_nil(VALUE self)
|
283
|
+
{
|
284
|
+
StringIO(self);
|
285
|
+
return Qnil;
|
286
|
+
}
|
287
|
+
|
288
|
+
/*
|
289
|
+
* Returns *strio* itself. Just for compatibility to IO.
|
290
|
+
*/
|
291
|
+
static VALUE
|
292
|
+
strio_self(VALUE self)
|
293
|
+
{
|
294
|
+
StringIO(self);
|
295
|
+
return self;
|
296
|
+
}
|
297
|
+
|
298
|
+
/*
|
299
|
+
* Returns 0. Just for compatibility to IO.
|
300
|
+
*/
|
301
|
+
static VALUE
|
302
|
+
strio_0(VALUE self)
|
303
|
+
{
|
304
|
+
StringIO(self);
|
305
|
+
return INT2FIX(0);
|
306
|
+
}
|
307
|
+
|
308
|
+
/*
|
309
|
+
* Returns the argument unchanged. Just for compatibility to IO.
|
310
|
+
*/
|
311
|
+
static VALUE
|
312
|
+
strio_first(VALUE self, VALUE arg)
|
313
|
+
{
|
314
|
+
StringIO(self);
|
315
|
+
return arg;
|
316
|
+
}
|
317
|
+
|
318
|
+
/*
|
319
|
+
* Raises NotImplementedError.
|
320
|
+
*/
|
321
|
+
static VALUE
|
322
|
+
strio_unimpl(int argc, VALUE *argv, VALUE self)
|
323
|
+
{
|
324
|
+
StringIO(self);
|
325
|
+
rb_notimplement();
|
326
|
+
|
327
|
+
UNREACHABLE;
|
328
|
+
}
|
329
|
+
|
330
|
+
/*
|
331
|
+
* call-seq: strio.string -> string
|
332
|
+
*
|
333
|
+
* Returns underlying String object, the subject of IO.
|
334
|
+
*/
|
335
|
+
static VALUE
|
336
|
+
strio_get_string(VALUE self)
|
337
|
+
{
|
338
|
+
return StringIO(self)->string;
|
339
|
+
}
|
340
|
+
|
341
|
+
/*
|
342
|
+
* call-seq:
|
343
|
+
* strio.string = string -> string
|
344
|
+
*
|
345
|
+
* Changes underlying String object, the subject of IO.
|
346
|
+
*/
|
347
|
+
static VALUE
|
348
|
+
strio_set_string(VALUE self, VALUE string)
|
349
|
+
{
|
350
|
+
struct StringIO *ptr = StringIO(self);
|
351
|
+
|
352
|
+
rb_io_taint_check(self);
|
353
|
+
ptr->flags &= ~FMODE_READWRITE;
|
354
|
+
StringValue(string);
|
355
|
+
ptr->flags = OBJ_FROZEN(string) ? FMODE_READABLE : FMODE_READWRITE;
|
356
|
+
ptr->pos = 0;
|
357
|
+
ptr->lineno = 0;
|
358
|
+
return ptr->string = string;
|
359
|
+
}
|
360
|
+
|
361
|
+
/*
|
362
|
+
* call-seq:
|
363
|
+
* strio.close -> nil
|
364
|
+
*
|
365
|
+
* Closes strio. The *strio* is unavailable for any further data
|
366
|
+
* operations; an +IOError+ is raised if such an attempt is made.
|
367
|
+
*/
|
368
|
+
static VALUE
|
369
|
+
strio_close(VALUE self)
|
370
|
+
{
|
371
|
+
StringIO(self);
|
372
|
+
RBASIC(self)->flags &= ~STRIO_READWRITE;
|
373
|
+
return Qnil;
|
374
|
+
}
|
375
|
+
|
376
|
+
/*
|
377
|
+
* call-seq:
|
378
|
+
* strio.close_read -> nil
|
379
|
+
*
|
380
|
+
* Closes the read end of a StringIO. Will raise an +IOError+ if the
|
381
|
+
* *strio* is not readable.
|
382
|
+
*/
|
383
|
+
static VALUE
|
384
|
+
strio_close_read(VALUE self)
|
385
|
+
{
|
386
|
+
struct StringIO *ptr = StringIO(self);
|
387
|
+
if (!(ptr->flags & FMODE_READABLE)) {
|
388
|
+
rb_raise(rb_eIOError, "closing non-duplex IO for reading");
|
389
|
+
}
|
390
|
+
RBASIC(self)->flags &= ~STRIO_READABLE;
|
391
|
+
return Qnil;
|
392
|
+
}
|
393
|
+
|
394
|
+
/*
|
395
|
+
* call-seq:
|
396
|
+
* strio.close_write -> nil
|
397
|
+
*
|
398
|
+
* Closes the write end of a StringIO. Will raise an +IOError+ if the
|
399
|
+
* *strio* is not writeable.
|
400
|
+
*/
|
401
|
+
static VALUE
|
402
|
+
strio_close_write(VALUE self)
|
403
|
+
{
|
404
|
+
struct StringIO *ptr = StringIO(self);
|
405
|
+
if (!(ptr->flags & FMODE_WRITABLE)) {
|
406
|
+
rb_raise(rb_eIOError, "closing non-duplex IO for writing");
|
407
|
+
}
|
408
|
+
RBASIC(self)->flags &= ~STRIO_WRITABLE;
|
409
|
+
return Qnil;
|
410
|
+
}
|
411
|
+
|
412
|
+
/*
|
413
|
+
* call-seq:
|
414
|
+
* strio.closed? -> true or false
|
415
|
+
*
|
416
|
+
* Returns +true+ if *strio* is completely closed, +false+ otherwise.
|
417
|
+
*/
|
418
|
+
static VALUE
|
419
|
+
strio_closed(VALUE self)
|
420
|
+
{
|
421
|
+
StringIO(self);
|
422
|
+
if (!CLOSED(self)) return Qfalse;
|
423
|
+
return Qtrue;
|
424
|
+
}
|
425
|
+
|
426
|
+
/*
|
427
|
+
* call-seq:
|
428
|
+
* strio.closed_read? -> true or false
|
429
|
+
*
|
430
|
+
* Returns +true+ if *strio* is not readable, +false+ otherwise.
|
431
|
+
*/
|
432
|
+
static VALUE
|
433
|
+
strio_closed_read(VALUE self)
|
434
|
+
{
|
435
|
+
StringIO(self);
|
436
|
+
if (READABLE(self)) return Qfalse;
|
437
|
+
return Qtrue;
|
438
|
+
}
|
439
|
+
|
440
|
+
/*
|
441
|
+
* call-seq:
|
442
|
+
* strio.closed_write? -> true or false
|
443
|
+
*
|
444
|
+
* Returns +true+ if *strio* is not writable, +false+ otherwise.
|
445
|
+
*/
|
446
|
+
static VALUE
|
447
|
+
strio_closed_write(VALUE self)
|
448
|
+
{
|
449
|
+
StringIO(self);
|
450
|
+
if (WRITABLE(self)) return Qfalse;
|
451
|
+
return Qtrue;
|
452
|
+
}
|
453
|
+
|
454
|
+
/*
|
455
|
+
* call-seq:
|
456
|
+
* strio.eof -> true or false
|
457
|
+
* strio.eof? -> true or false
|
458
|
+
*
|
459
|
+
* Returns true if *strio* is at end of file. The stringio must be
|
460
|
+
* opened for reading or an +IOError+ will be raised.
|
461
|
+
*/
|
462
|
+
static VALUE
|
463
|
+
strio_eof(VALUE self)
|
464
|
+
{
|
465
|
+
struct StringIO *ptr = readable(self);
|
466
|
+
if (ptr->pos < RSTRING_LEN(ptr->string)) return Qfalse;
|
467
|
+
return Qtrue;
|
468
|
+
}
|
469
|
+
|
470
|
+
/* :nodoc: */
|
471
|
+
static VALUE
|
472
|
+
strio_copy(VALUE copy, VALUE orig)
|
473
|
+
{
|
474
|
+
struct StringIO *ptr;
|
475
|
+
|
476
|
+
orig = rb_convert_type(orig, T_DATA, "StringIO", "to_strio");
|
477
|
+
if (copy == orig) return copy;
|
478
|
+
ptr = StringIO(orig);
|
479
|
+
if (check_strio(copy)) {
|
480
|
+
strio_free(DATA_PTR(copy));
|
481
|
+
}
|
482
|
+
DATA_PTR(copy) = ptr;
|
483
|
+
OBJ_INFECT(copy, orig);
|
484
|
+
RBASIC(copy)->flags &= ~STRIO_READWRITE;
|
485
|
+
RBASIC(copy)->flags |= RBASIC(orig)->flags & STRIO_READWRITE;
|
486
|
+
++ptr->count;
|
487
|
+
return copy;
|
488
|
+
}
|
489
|
+
|
490
|
+
/*
|
491
|
+
* call-seq:
|
492
|
+
* strio.lineno -> integer
|
493
|
+
*
|
494
|
+
* Returns the current line number in *strio*. The stringio must be
|
495
|
+
* opened for reading. +lineno+ counts the number of times +gets+ is
|
496
|
+
* called, rather than the number of newlines encountered. The two
|
497
|
+
* values will differ if +gets+ is called with a separator other than
|
498
|
+
* newline. See also the <code>$.</code> variable.
|
499
|
+
*/
|
500
|
+
static VALUE
|
501
|
+
strio_get_lineno(VALUE self)
|
502
|
+
{
|
503
|
+
return LONG2NUM(StringIO(self)->lineno);
|
504
|
+
}
|
505
|
+
|
506
|
+
/*
|
507
|
+
* call-seq:
|
508
|
+
* strio.lineno = integer -> integer
|
509
|
+
*
|
510
|
+
* Manually sets the current line number to the given value.
|
511
|
+
* <code>$.</code> is updated only on the next read.
|
512
|
+
*/
|
513
|
+
static VALUE
|
514
|
+
strio_set_lineno(VALUE self, VALUE lineno)
|
515
|
+
{
|
516
|
+
StringIO(self)->lineno = NUM2LONG(lineno);
|
517
|
+
return lineno;
|
518
|
+
}
|
519
|
+
|
520
|
+
static VALUE
|
521
|
+
strio_binmode(VALUE self)
|
522
|
+
{
|
523
|
+
struct StringIO *ptr = StringIO(self);
|
524
|
+
rb_encoding *enc = rb_ascii8bit_encoding();
|
525
|
+
|
526
|
+
ptr->enc = enc;
|
527
|
+
if (WRITABLE(self)) {
|
528
|
+
rb_enc_associate(ptr->string, enc);
|
529
|
+
}
|
530
|
+
return self;
|
531
|
+
}
|
532
|
+
|
533
|
+
#define strio_fcntl strio_unimpl
|
534
|
+
|
535
|
+
#define strio_flush strio_self
|
536
|
+
|
537
|
+
#define strio_fsync strio_0
|
538
|
+
|
539
|
+
/*
|
540
|
+
* call-seq:
|
541
|
+
* strio.reopen(other_StrIO) -> strio
|
542
|
+
* strio.reopen(string, mode) -> strio
|
543
|
+
*
|
544
|
+
* Reinitializes *strio* with the given <i>other_StrIO</i> or _string_
|
545
|
+
* and _mode_ (see StringIO#new).
|
546
|
+
*/
|
547
|
+
static VALUE
|
548
|
+
strio_reopen(int argc, VALUE *argv, VALUE self)
|
549
|
+
{
|
550
|
+
rb_io_taint_check(self);
|
551
|
+
if (argc == 1 && !RB_TYPE_P(*argv, T_STRING)) {
|
552
|
+
return strio_copy(self, *argv);
|
553
|
+
}
|
554
|
+
return strio_init(argc, argv, StringIO(self), self);
|
555
|
+
}
|
556
|
+
|
557
|
+
/*
|
558
|
+
* call-seq:
|
559
|
+
* strio.pos -> integer
|
560
|
+
* strio.tell -> integer
|
561
|
+
*
|
562
|
+
* Returns the current offset (in bytes) of *strio*.
|
563
|
+
*/
|
564
|
+
static VALUE
|
565
|
+
strio_get_pos(VALUE self)
|
566
|
+
{
|
567
|
+
return LONG2NUM(StringIO(self)->pos);
|
568
|
+
}
|
569
|
+
|
570
|
+
/*
|
571
|
+
* call-seq:
|
572
|
+
* strio.pos = integer -> integer
|
573
|
+
*
|
574
|
+
* Seeks to the given position (in bytes) in *strio*.
|
575
|
+
*/
|
576
|
+
static VALUE
|
577
|
+
strio_set_pos(VALUE self, VALUE pos)
|
578
|
+
{
|
579
|
+
struct StringIO *ptr = StringIO(self);
|
580
|
+
long p = NUM2LONG(pos);
|
581
|
+
if (p < 0) {
|
582
|
+
error_inval(0);
|
583
|
+
}
|
584
|
+
ptr->pos = p;
|
585
|
+
return pos;
|
586
|
+
}
|
587
|
+
|
588
|
+
/*
|
589
|
+
* call-seq:
|
590
|
+
* strio.rewind -> 0
|
591
|
+
*
|
592
|
+
* Positions *strio* to the beginning of input, resetting
|
593
|
+
* +lineno+ to zero.
|
594
|
+
*/
|
595
|
+
static VALUE
|
596
|
+
strio_rewind(VALUE self)
|
597
|
+
{
|
598
|
+
struct StringIO *ptr = StringIO(self);
|
599
|
+
ptr->pos = 0;
|
600
|
+
ptr->lineno = 0;
|
601
|
+
return INT2FIX(0);
|
602
|
+
}
|
603
|
+
|
604
|
+
/*
|
605
|
+
* call-seq:
|
606
|
+
* strio.seek(amount, whence=SEEK_SET) -> 0
|
607
|
+
*
|
608
|
+
* Seeks to a given offset _amount_ in the stream according to
|
609
|
+
* the value of _whence_ (see IO#seek).
|
610
|
+
*/
|
611
|
+
static VALUE
|
612
|
+
strio_seek(int argc, VALUE *argv, VALUE self)
|
613
|
+
{
|
614
|
+
VALUE whence;
|
615
|
+
struct StringIO *ptr = StringIO(self);
|
616
|
+
long amount, offset;
|
617
|
+
|
618
|
+
rb_scan_args(argc, argv, "11", NULL, &whence);
|
619
|
+
amount = NUM2LONG(argv[0]);
|
620
|
+
if (CLOSED(self)) {
|
621
|
+
rb_raise(rb_eIOError, "closed stream");
|
622
|
+
}
|
623
|
+
switch (NIL_P(whence) ? 0 : NUM2LONG(whence)) {
|
624
|
+
case 0:
|
625
|
+
offset = 0;
|
626
|
+
break;
|
627
|
+
case 1:
|
628
|
+
offset = ptr->pos;
|
629
|
+
break;
|
630
|
+
case 2:
|
631
|
+
offset = RSTRING_LEN(ptr->string);
|
632
|
+
break;
|
633
|
+
default:
|
634
|
+
error_inval("invalid whence");
|
635
|
+
}
|
636
|
+
if (amount > LONG_MAX - offset || amount + offset < 0) {
|
637
|
+
error_inval(0);
|
638
|
+
}
|
639
|
+
ptr->pos = amount + offset;
|
640
|
+
return INT2FIX(0);
|
641
|
+
}
|
642
|
+
|
643
|
+
/*
|
644
|
+
* call-seq:
|
645
|
+
* strio.sync -> true
|
646
|
+
*
|
647
|
+
* Returns +true+ always.
|
648
|
+
*/
|
649
|
+
static VALUE
|
650
|
+
strio_get_sync(VALUE self)
|
651
|
+
{
|
652
|
+
StringIO(self);
|
653
|
+
return Qtrue;
|
654
|
+
}
|
655
|
+
|
656
|
+
#define strio_set_sync strio_first
|
657
|
+
|
658
|
+
#define strio_tell strio_get_pos
|
659
|
+
|
660
|
+
/*
|
661
|
+
* call-seq:
|
662
|
+
* strio.each_byte {|byte| block } -> strio
|
663
|
+
* strio.each_byte -> anEnumerator
|
664
|
+
*
|
665
|
+
* See IO#each_byte.
|
666
|
+
*/
|
667
|
+
static VALUE
|
668
|
+
strio_each_byte(VALUE self)
|
669
|
+
{
|
670
|
+
struct StringIO *ptr = readable(self);
|
671
|
+
|
672
|
+
RETURN_ENUMERATOR(self, 0, 0);
|
673
|
+
|
674
|
+
while (ptr->pos < RSTRING_LEN(ptr->string)) {
|
675
|
+
char c = RSTRING_PTR(ptr->string)[ptr->pos++];
|
676
|
+
rb_yield(CHR2FIX(c));
|
677
|
+
}
|
678
|
+
return self;
|
679
|
+
}
|
680
|
+
|
681
|
+
/*
|
682
|
+
* This is a deprecated alias for #each_byte.
|
683
|
+
*/
|
684
|
+
static VALUE
|
685
|
+
strio_bytes(VALUE self)
|
686
|
+
{
|
687
|
+
rb_warn("StringIO#bytes is deprecated; use #each_byte instead");
|
688
|
+
if (!rb_block_given_p())
|
689
|
+
return rb_enumeratorize(self, ID2SYM(rb_intern("each_byte")), 0, 0);
|
690
|
+
return strio_each_byte(self);
|
691
|
+
}
|
692
|
+
|
693
|
+
/*
|
694
|
+
* call-seq:
|
695
|
+
* strio.getc -> string or nil
|
696
|
+
*
|
697
|
+
* See IO#getc.
|
698
|
+
*/
|
699
|
+
static VALUE
|
700
|
+
strio_getc(VALUE self)
|
701
|
+
{
|
702
|
+
struct StringIO *ptr = readable(self);
|
703
|
+
rb_encoding *enc = get_enc(ptr);
|
704
|
+
VALUE str = ptr->string;
|
705
|
+
long pos = ptr->pos;
|
706
|
+
int len;
|
707
|
+
char *p;
|
708
|
+
|
709
|
+
if (pos >= RSTRING_LEN(str)) {
|
710
|
+
return Qnil;
|
711
|
+
}
|
712
|
+
p = RSTRING_PTR(str)+pos;
|
713
|
+
len = rb_enc_mbclen(p, RSTRING_END(str), enc);
|
714
|
+
ptr->pos += len;
|
715
|
+
return enc_subseq(str, pos, len, enc);
|
716
|
+
}
|
717
|
+
|
718
|
+
/*
|
719
|
+
* call-seq:
|
720
|
+
* strio.getbyte -> fixnum or nil
|
721
|
+
*
|
722
|
+
* See IO#getbyte.
|
723
|
+
*/
|
724
|
+
static VALUE
|
725
|
+
strio_getbyte(VALUE self)
|
726
|
+
{
|
727
|
+
struct StringIO *ptr = readable(self);
|
728
|
+
int c;
|
729
|
+
if (ptr->pos >= RSTRING_LEN(ptr->string)) {
|
730
|
+
return Qnil;
|
731
|
+
}
|
732
|
+
c = RSTRING_PTR(ptr->string)[ptr->pos++];
|
733
|
+
return CHR2FIX(c);
|
734
|
+
}
|
735
|
+
|
736
|
+
static void
|
737
|
+
strio_extend(struct StringIO *ptr, long pos, long len)
|
738
|
+
{
|
739
|
+
long olen;
|
740
|
+
|
741
|
+
if (len > LONG_MAX - pos)
|
742
|
+
rb_raise(rb_eArgError, "string size too big");
|
743
|
+
|
744
|
+
check_modifiable(ptr);
|
745
|
+
olen = RSTRING_LEN(ptr->string);
|
746
|
+
if (pos + len > olen) {
|
747
|
+
rb_str_resize(ptr->string, pos + len);
|
748
|
+
if (pos > olen)
|
749
|
+
MEMZERO(RSTRING_PTR(ptr->string) + olen, char, pos - olen);
|
750
|
+
}
|
751
|
+
else {
|
752
|
+
rb_str_modify(ptr->string);
|
753
|
+
}
|
754
|
+
}
|
755
|
+
|
756
|
+
/*
|
757
|
+
* call-seq:
|
758
|
+
* strio.ungetc(string) -> nil
|
759
|
+
*
|
760
|
+
* Pushes back one character (passed as a parameter) onto *strio*
|
761
|
+
* such that a subsequent buffered read will return it. There is no
|
762
|
+
* limitation for multiple pushbacks including pushing back behind the
|
763
|
+
* beginning of the buffer string.
|
764
|
+
*/
|
765
|
+
static VALUE
|
766
|
+
strio_ungetc(VALUE self, VALUE c)
|
767
|
+
{
|
768
|
+
struct StringIO *ptr = readable(self);
|
769
|
+
rb_encoding *enc, *enc2;
|
770
|
+
|
771
|
+
check_modifiable(ptr);
|
772
|
+
if (NIL_P(c)) return Qnil;
|
773
|
+
if (RB_INTEGER_TYPE_P(c)) {
|
774
|
+
int len, cc = NUM2INT(c);
|
775
|
+
char buf[16];
|
776
|
+
|
777
|
+
enc = rb_enc_get(ptr->string);
|
778
|
+
len = rb_enc_codelen(cc, enc);
|
779
|
+
if (len <= 0) rb_enc_uint_chr(cc, enc);
|
780
|
+
rb_enc_mbcput(cc, buf, enc);
|
781
|
+
return strio_unget_bytes(ptr, buf, len);
|
782
|
+
}
|
783
|
+
else {
|
784
|
+
SafeStringValue(c);
|
785
|
+
enc = rb_enc_get(ptr->string);
|
786
|
+
enc2 = rb_enc_get(c);
|
787
|
+
if (enc != enc2 && enc != rb_ascii8bit_encoding()) {
|
788
|
+
c = rb_str_conv_enc(c, enc2, enc);
|
789
|
+
}
|
790
|
+
strio_unget_bytes(ptr, RSTRING_PTR(c), RSTRING_LEN(c));
|
791
|
+
RB_GC_GUARD(c);
|
792
|
+
return Qnil;
|
793
|
+
}
|
794
|
+
}
|
795
|
+
|
796
|
+
/*
|
797
|
+
* call-seq:
|
798
|
+
* strio.ungetbyte(fixnum) -> nil
|
799
|
+
*
|
800
|
+
* See IO#ungetbyte
|
801
|
+
*/
|
802
|
+
static VALUE
|
803
|
+
strio_ungetbyte(VALUE self, VALUE c)
|
804
|
+
{
|
805
|
+
struct StringIO *ptr = readable(self);
|
806
|
+
char buf[1], *cp = buf;
|
807
|
+
long cl = 1;
|
808
|
+
|
809
|
+
check_modifiable(ptr);
|
810
|
+
if (NIL_P(c)) return Qnil;
|
811
|
+
if (FIXNUM_P(c)) {
|
812
|
+
buf[0] = (char)FIX2INT(c);
|
813
|
+
return strio_unget_bytes(ptr, buf, 1);
|
814
|
+
}
|
815
|
+
else {
|
816
|
+
SafeStringValue(c);
|
817
|
+
cp = RSTRING_PTR(c);
|
818
|
+
cl = RSTRING_LEN(c);
|
819
|
+
if (cl == 0) return Qnil;
|
820
|
+
strio_unget_bytes(ptr, cp, cl);
|
821
|
+
RB_GC_GUARD(c);
|
822
|
+
return Qnil;
|
823
|
+
}
|
824
|
+
}
|
825
|
+
|
826
|
+
static VALUE
|
827
|
+
strio_unget_bytes(struct StringIO *ptr, const char *cp, long cl)
|
828
|
+
{
|
829
|
+
long pos = ptr->pos, len, rest;
|
830
|
+
VALUE str = ptr->string;
|
831
|
+
char *s;
|
832
|
+
|
833
|
+
len = RSTRING_LEN(str);
|
834
|
+
rest = pos - len;
|
835
|
+
if (cl > pos) {
|
836
|
+
long ex = (rest < 0 ? cl-pos : cl+rest);
|
837
|
+
rb_str_modify_expand(str, ex);
|
838
|
+
rb_str_set_len(str, len + ex);
|
839
|
+
s = RSTRING_PTR(str);
|
840
|
+
if (rest < 0) memmove(s + cl, s + pos, -rest);
|
841
|
+
pos = 0;
|
842
|
+
}
|
843
|
+
else {
|
844
|
+
if (rest > 0) {
|
845
|
+
rb_str_modify_expand(str, rest);
|
846
|
+
rb_str_set_len(str, len + rest);
|
847
|
+
}
|
848
|
+
s = RSTRING_PTR(str);
|
849
|
+
if (rest > cl) memset(s + len, 0, rest - cl);
|
850
|
+
pos -= cl;
|
851
|
+
}
|
852
|
+
memcpy(s + pos, cp, cl);
|
853
|
+
ptr->pos = pos;
|
854
|
+
return Qnil;
|
855
|
+
}
|
856
|
+
|
857
|
+
/*
|
858
|
+
* call-seq:
|
859
|
+
* strio.readchar -> string
|
860
|
+
*
|
861
|
+
* See IO#readchar.
|
862
|
+
*/
|
863
|
+
static VALUE
|
864
|
+
strio_readchar(VALUE self)
|
865
|
+
{
|
866
|
+
VALUE c = rb_funcall2(self, rb_intern("getc"), 0, 0);
|
867
|
+
if (NIL_P(c)) rb_eof_error();
|
868
|
+
return c;
|
869
|
+
}
|
870
|
+
|
871
|
+
/*
|
872
|
+
* call-seq:
|
873
|
+
* strio.readbyte -> fixnum
|
874
|
+
*
|
875
|
+
* See IO#readbyte.
|
876
|
+
*/
|
877
|
+
static VALUE
|
878
|
+
strio_readbyte(VALUE self)
|
879
|
+
{
|
880
|
+
VALUE c = rb_funcall2(self, rb_intern("getbyte"), 0, 0);
|
881
|
+
if (NIL_P(c)) rb_eof_error();
|
882
|
+
return c;
|
883
|
+
}
|
884
|
+
|
885
|
+
/*
|
886
|
+
* call-seq:
|
887
|
+
* strio.each_char {|char| block } -> strio
|
888
|
+
* strio.each_char -> anEnumerator
|
889
|
+
*
|
890
|
+
* See IO#each_char.
|
891
|
+
*/
|
892
|
+
static VALUE
|
893
|
+
strio_each_char(VALUE self)
|
894
|
+
{
|
895
|
+
VALUE c;
|
896
|
+
|
897
|
+
RETURN_ENUMERATOR(self, 0, 0);
|
898
|
+
|
899
|
+
while (!NIL_P(c = strio_getc(self))) {
|
900
|
+
rb_yield(c);
|
901
|
+
}
|
902
|
+
return self;
|
903
|
+
}
|
904
|
+
|
905
|
+
/*
|
906
|
+
* This is a deprecated alias for <code>each_char</code>.
|
907
|
+
*/
|
908
|
+
static VALUE
|
909
|
+
strio_chars(VALUE self)
|
910
|
+
{
|
911
|
+
rb_warn("StringIO#chars is deprecated; use #each_char instead");
|
912
|
+
if (!rb_block_given_p())
|
913
|
+
return rb_enumeratorize(self, ID2SYM(rb_intern("each_char")), 0, 0);
|
914
|
+
return strio_each_char(self);
|
915
|
+
}
|
916
|
+
|
917
|
+
/*
|
918
|
+
* call-seq:
|
919
|
+
* strio.each_codepoint {|c| block } -> strio
|
920
|
+
* strio.each_codepoint -> anEnumerator
|
921
|
+
*
|
922
|
+
* See IO#each_codepoint.
|
923
|
+
*/
|
924
|
+
static VALUE
|
925
|
+
strio_each_codepoint(VALUE self)
|
926
|
+
{
|
927
|
+
struct StringIO *ptr;
|
928
|
+
rb_encoding *enc;
|
929
|
+
unsigned int c;
|
930
|
+
int n;
|
931
|
+
|
932
|
+
RETURN_ENUMERATOR(self, 0, 0);
|
933
|
+
|
934
|
+
ptr = readable(self);
|
935
|
+
enc = get_enc(ptr);
|
936
|
+
for (;;) {
|
937
|
+
if (ptr->pos >= RSTRING_LEN(ptr->string)) {
|
938
|
+
return self;
|
939
|
+
}
|
940
|
+
|
941
|
+
c = rb_enc_codepoint_len(RSTRING_PTR(ptr->string)+ptr->pos,
|
942
|
+
RSTRING_END(ptr->string), &n, enc);
|
943
|
+
rb_yield(UINT2NUM(c));
|
944
|
+
ptr->pos += n;
|
945
|
+
}
|
946
|
+
return self;
|
947
|
+
}
|
948
|
+
|
949
|
+
/*
|
950
|
+
* This is a deprecated alias for <code>each_codepoint</code>.
|
951
|
+
*/
|
952
|
+
static VALUE
|
953
|
+
strio_codepoints(VALUE self)
|
954
|
+
{
|
955
|
+
rb_warn("StringIO#codepoints is deprecated; use #each_codepoint instead");
|
956
|
+
if (!rb_block_given_p())
|
957
|
+
return rb_enumeratorize(self, ID2SYM(rb_intern("each_codepoint")), 0, 0);
|
958
|
+
return strio_each_codepoint(self);
|
959
|
+
}
|
960
|
+
|
961
|
+
/* Boyer-Moore search: copied from regex.c */
|
962
|
+
static void
|
963
|
+
bm_init_skip(long *skip, const char *pat, long m)
|
964
|
+
{
|
965
|
+
int c;
|
966
|
+
|
967
|
+
for (c = 0; c < (1 << CHAR_BIT); c++) {
|
968
|
+
skip[c] = m;
|
969
|
+
}
|
970
|
+
while (--m) {
|
971
|
+
skip[(unsigned char)*pat++] = m;
|
972
|
+
}
|
973
|
+
}
|
974
|
+
|
975
|
+
static long
|
976
|
+
bm_search(const char *little, long llen, const char *big, long blen, const long *skip)
|
977
|
+
{
|
978
|
+
long i, j, k;
|
979
|
+
|
980
|
+
i = llen - 1;
|
981
|
+
while (i < blen) {
|
982
|
+
k = i;
|
983
|
+
j = llen - 1;
|
984
|
+
while (j >= 0 && big[k] == little[j]) {
|
985
|
+
k--;
|
986
|
+
j--;
|
987
|
+
}
|
988
|
+
if (j < 0) return k + 1;
|
989
|
+
i += skip[(unsigned char)big[i]];
|
990
|
+
}
|
991
|
+
return -1;
|
992
|
+
}
|
993
|
+
|
994
|
+
struct getline_arg {
|
995
|
+
VALUE rs;
|
996
|
+
long limit;
|
997
|
+
unsigned int chomp: 1;
|
998
|
+
};
|
999
|
+
|
1000
|
+
static struct getline_arg *
|
1001
|
+
prepare_getline_args(struct getline_arg *arg, int argc, VALUE *argv)
|
1002
|
+
{
|
1003
|
+
VALUE str, lim, opts;
|
1004
|
+
long limit = -1;
|
1005
|
+
|
1006
|
+
argc = rb_scan_args(argc, argv, "02:", &str, &lim, &opts);
|
1007
|
+
switch (argc) {
|
1008
|
+
case 0:
|
1009
|
+
str = rb_rs;
|
1010
|
+
break;
|
1011
|
+
|
1012
|
+
case 1:
|
1013
|
+
if (!NIL_P(str) && !RB_TYPE_P(str, T_STRING)) {
|
1014
|
+
VALUE tmp = rb_check_string_type(str);
|
1015
|
+
if (NIL_P(tmp)) {
|
1016
|
+
limit = NUM2LONG(str);
|
1017
|
+
str = rb_rs;
|
1018
|
+
}
|
1019
|
+
else {
|
1020
|
+
str = tmp;
|
1021
|
+
}
|
1022
|
+
}
|
1023
|
+
break;
|
1024
|
+
|
1025
|
+
case 2:
|
1026
|
+
if (!NIL_P(str)) StringValue(str);
|
1027
|
+
if (!NIL_P(lim)) limit = NUM2LONG(lim);
|
1028
|
+
break;
|
1029
|
+
}
|
1030
|
+
arg->rs = str;
|
1031
|
+
arg->limit = limit;
|
1032
|
+
arg->chomp = 0;
|
1033
|
+
if (!NIL_P(opts)) {
|
1034
|
+
static ID keywords[1];
|
1035
|
+
VALUE vchomp;
|
1036
|
+
if (!keywords[0]) {
|
1037
|
+
keywords[0] = rb_intern_const("chomp");
|
1038
|
+
}
|
1039
|
+
rb_get_kwargs(opts, keywords, 0, 1, &vchomp);
|
1040
|
+
arg->chomp = (vchomp != Qundef) && RTEST(vchomp);
|
1041
|
+
}
|
1042
|
+
return arg;
|
1043
|
+
}
|
1044
|
+
|
1045
|
+
static inline int
|
1046
|
+
chomp_newline_width(const char *s, const char *e)
|
1047
|
+
{
|
1048
|
+
if (e > s && *--e == '\n') {
|
1049
|
+
if (e > s && *--e == '\r') return 2;
|
1050
|
+
return 1;
|
1051
|
+
}
|
1052
|
+
return 0;
|
1053
|
+
}
|
1054
|
+
|
1055
|
+
static VALUE
|
1056
|
+
strio_getline(struct getline_arg *arg, struct StringIO *ptr)
|
1057
|
+
{
|
1058
|
+
const char *s, *e, *p;
|
1059
|
+
long n, limit = arg->limit;
|
1060
|
+
VALUE str = arg->rs;
|
1061
|
+
int w = 0;
|
1062
|
+
rb_encoding *enc = get_enc(ptr);
|
1063
|
+
|
1064
|
+
if (ptr->pos >= (n = RSTRING_LEN(ptr->string))) {
|
1065
|
+
return Qnil;
|
1066
|
+
}
|
1067
|
+
s = RSTRING_PTR(ptr->string);
|
1068
|
+
e = s + RSTRING_LEN(ptr->string);
|
1069
|
+
s += ptr->pos;
|
1070
|
+
if (limit > 0 && (size_t)limit < (size_t)(e - s)) {
|
1071
|
+
e = rb_enc_right_char_head(s, s + limit, e, get_enc(ptr));
|
1072
|
+
}
|
1073
|
+
if (NIL_P(str)) {
|
1074
|
+
if (arg->chomp) {
|
1075
|
+
w = chomp_newline_width(s, e);
|
1076
|
+
}
|
1077
|
+
str = strio_substr(ptr, ptr->pos, e - s - w, enc);
|
1078
|
+
}
|
1079
|
+
else if ((n = RSTRING_LEN(str)) == 0) {
|
1080
|
+
p = s;
|
1081
|
+
while (p[(p + 1 < e) && (*p == '\r') && 0] == '\n') {
|
1082
|
+
p += *p == '\r';
|
1083
|
+
if (++p == e) {
|
1084
|
+
return Qnil;
|
1085
|
+
}
|
1086
|
+
}
|
1087
|
+
s = p;
|
1088
|
+
while ((p = memchr(p, '\n', e - p)) && (p != e)) {
|
1089
|
+
if (*++p == '\n') {
|
1090
|
+
e = p + 1;
|
1091
|
+
w = (arg->chomp ? 1 : 0);
|
1092
|
+
break;
|
1093
|
+
}
|
1094
|
+
else if (*p == '\r' && p < e && p[1] == '\n') {
|
1095
|
+
e = p + 2;
|
1096
|
+
w = (arg->chomp ? 2 : 0);
|
1097
|
+
break;
|
1098
|
+
}
|
1099
|
+
}
|
1100
|
+
if (!w && arg->chomp) {
|
1101
|
+
w = chomp_newline_width(s, e);
|
1102
|
+
}
|
1103
|
+
str = strio_substr(ptr, s - RSTRING_PTR(ptr->string), e - s - w, enc);
|
1104
|
+
}
|
1105
|
+
else if (n == 1) {
|
1106
|
+
if ((p = memchr(s, RSTRING_PTR(str)[0], e - s)) != 0) {
|
1107
|
+
e = p + 1;
|
1108
|
+
w = (arg->chomp ? (p > s && *(p-1) == '\r') + 1 : 0);
|
1109
|
+
}
|
1110
|
+
str = strio_substr(ptr, ptr->pos, e - s - w, enc);
|
1111
|
+
}
|
1112
|
+
else {
|
1113
|
+
if (n < e - s) {
|
1114
|
+
if (e - s < 1024) {
|
1115
|
+
for (p = s; p + n <= e; ++p) {
|
1116
|
+
if (MEMCMP(p, RSTRING_PTR(str), char, n) == 0) {
|
1117
|
+
e = p + (arg->chomp ? 0 : n);
|
1118
|
+
break;
|
1119
|
+
}
|
1120
|
+
}
|
1121
|
+
}
|
1122
|
+
else {
|
1123
|
+
long skip[1 << CHAR_BIT], pos;
|
1124
|
+
p = RSTRING_PTR(str);
|
1125
|
+
bm_init_skip(skip, p, n);
|
1126
|
+
if ((pos = bm_search(p, n, s, e - s, skip)) >= 0) {
|
1127
|
+
e = s + pos + (arg->chomp ? 0 : n);
|
1128
|
+
}
|
1129
|
+
}
|
1130
|
+
}
|
1131
|
+
str = strio_substr(ptr, ptr->pos, e - s - w, enc);
|
1132
|
+
}
|
1133
|
+
ptr->pos = e - RSTRING_PTR(ptr->string);
|
1134
|
+
ptr->lineno++;
|
1135
|
+
return str;
|
1136
|
+
}
|
1137
|
+
|
1138
|
+
/*
|
1139
|
+
* call-seq:
|
1140
|
+
* strio.gets(sep=$/) -> string or nil
|
1141
|
+
* strio.gets(limit) -> string or nil
|
1142
|
+
* strio.gets(sep, limit) -> string or nil
|
1143
|
+
*
|
1144
|
+
* See IO#gets.
|
1145
|
+
*/
|
1146
|
+
static VALUE
|
1147
|
+
strio_gets(int argc, VALUE *argv, VALUE self)
|
1148
|
+
{
|
1149
|
+
struct getline_arg arg;
|
1150
|
+
VALUE str;
|
1151
|
+
|
1152
|
+
if (prepare_getline_args(&arg, argc, argv)->limit == 0) {
|
1153
|
+
struct StringIO *ptr = readable(self);
|
1154
|
+
return rb_enc_str_new(0, 0, get_enc(ptr));
|
1155
|
+
}
|
1156
|
+
|
1157
|
+
str = strio_getline(&arg, readable(self));
|
1158
|
+
rb_lastline_set(str);
|
1159
|
+
return str;
|
1160
|
+
}
|
1161
|
+
|
1162
|
+
/*
|
1163
|
+
* call-seq:
|
1164
|
+
* strio.readline(sep=$/) -> string
|
1165
|
+
* strio.readline(limit) -> string or nil
|
1166
|
+
* strio.readline(sep, limit) -> string or nil
|
1167
|
+
*
|
1168
|
+
* See IO#readline.
|
1169
|
+
*/
|
1170
|
+
static VALUE
|
1171
|
+
strio_readline(int argc, VALUE *argv, VALUE self)
|
1172
|
+
{
|
1173
|
+
VALUE line = rb_funcall2(self, rb_intern("gets"), argc, argv);
|
1174
|
+
if (NIL_P(line)) rb_eof_error();
|
1175
|
+
return line;
|
1176
|
+
}
|
1177
|
+
|
1178
|
+
/*
|
1179
|
+
* call-seq:
|
1180
|
+
* strio.each(sep=$/) {|line| block } -> strio
|
1181
|
+
* strio.each(limit) {|line| block } -> strio
|
1182
|
+
* strio.each(sep, limit) {|line| block } -> strio
|
1183
|
+
* strio.each(...) -> anEnumerator
|
1184
|
+
*
|
1185
|
+
* strio.each_line(sep=$/) {|line| block } -> strio
|
1186
|
+
* strio.each_line(limit) {|line| block } -> strio
|
1187
|
+
* strio.each_line(sep,limit) {|line| block } -> strio
|
1188
|
+
* strio.each_line(...) -> anEnumerator
|
1189
|
+
*
|
1190
|
+
* See IO#each.
|
1191
|
+
*/
|
1192
|
+
static VALUE
|
1193
|
+
strio_each(int argc, VALUE *argv, VALUE self)
|
1194
|
+
{
|
1195
|
+
VALUE line;
|
1196
|
+
struct getline_arg arg;
|
1197
|
+
|
1198
|
+
StringIO(self);
|
1199
|
+
RETURN_ENUMERATOR(self, argc, argv);
|
1200
|
+
|
1201
|
+
if (prepare_getline_args(&arg, argc, argv)->limit == 0) {
|
1202
|
+
rb_raise(rb_eArgError, "invalid limit: 0 for each_line");
|
1203
|
+
}
|
1204
|
+
|
1205
|
+
while (!NIL_P(line = strio_getline(&arg, readable(self)))) {
|
1206
|
+
rb_yield(line);
|
1207
|
+
}
|
1208
|
+
return self;
|
1209
|
+
}
|
1210
|
+
|
1211
|
+
/*
|
1212
|
+
* This is a deprecated alias for <code>each_line</code>.
|
1213
|
+
*/
|
1214
|
+
static VALUE
|
1215
|
+
strio_lines(int argc, VALUE *argv, VALUE self)
|
1216
|
+
{
|
1217
|
+
rb_warn("StringIO#lines is deprecated; use #each_line instead");
|
1218
|
+
if (!rb_block_given_p())
|
1219
|
+
return rb_enumeratorize(self, ID2SYM(rb_intern("each_line")), argc, argv);
|
1220
|
+
return strio_each(argc, argv, self);
|
1221
|
+
}
|
1222
|
+
|
1223
|
+
/*
|
1224
|
+
* call-seq:
|
1225
|
+
* strio.readlines(sep=$/) -> array
|
1226
|
+
* strio.readlines(limit) -> array
|
1227
|
+
* strio.readlines(sep,limit) -> array
|
1228
|
+
*
|
1229
|
+
* See IO#readlines.
|
1230
|
+
*/
|
1231
|
+
static VALUE
|
1232
|
+
strio_readlines(int argc, VALUE *argv, VALUE self)
|
1233
|
+
{
|
1234
|
+
VALUE ary, line;
|
1235
|
+
struct getline_arg arg;
|
1236
|
+
|
1237
|
+
StringIO(self);
|
1238
|
+
ary = rb_ary_new();
|
1239
|
+
if (prepare_getline_args(&arg, argc, argv)->limit == 0) {
|
1240
|
+
rb_raise(rb_eArgError, "invalid limit: 0 for readlines");
|
1241
|
+
}
|
1242
|
+
|
1243
|
+
while (!NIL_P(line = strio_getline(&arg, readable(self)))) {
|
1244
|
+
rb_ary_push(ary, line);
|
1245
|
+
}
|
1246
|
+
return ary;
|
1247
|
+
}
|
1248
|
+
|
1249
|
+
/*
|
1250
|
+
* call-seq:
|
1251
|
+
* strio.write(string, ...) -> integer
|
1252
|
+
* strio.syswrite(string) -> integer
|
1253
|
+
*
|
1254
|
+
* Appends the given string to the underlying buffer string of *strio*.
|
1255
|
+
* The stream must be opened for writing. If the argument is not a
|
1256
|
+
* string, it will be converted to a string using <code>to_s</code>.
|
1257
|
+
* Returns the number of bytes written. See IO#write.
|
1258
|
+
*/
|
1259
|
+
static VALUE
|
1260
|
+
strio_write_m(int argc, VALUE *argv, VALUE self)
|
1261
|
+
{
|
1262
|
+
long len = 0;
|
1263
|
+
while (argc-- > 0) {
|
1264
|
+
/* StringIO can't exceed long limit */
|
1265
|
+
len += strio_write(self, *argv++);
|
1266
|
+
}
|
1267
|
+
return LONG2NUM(len);
|
1268
|
+
}
|
1269
|
+
|
1270
|
+
static long
|
1271
|
+
strio_write(VALUE self, VALUE str)
|
1272
|
+
{
|
1273
|
+
struct StringIO *ptr = writable(self);
|
1274
|
+
long len, olen;
|
1275
|
+
rb_encoding *enc, *enc2;
|
1276
|
+
rb_encoding *const ascii8bit = rb_ascii8bit_encoding();
|
1277
|
+
|
1278
|
+
if (!RB_TYPE_P(str, T_STRING))
|
1279
|
+
str = rb_obj_as_string(str);
|
1280
|
+
enc = get_enc(ptr);
|
1281
|
+
enc2 = rb_enc_get(str);
|
1282
|
+
if (enc != enc2 && enc != ascii8bit) {
|
1283
|
+
str = rb_str_conv_enc(str, enc2, enc);
|
1284
|
+
}
|
1285
|
+
len = RSTRING_LEN(str);
|
1286
|
+
if (len == 0) return 0;
|
1287
|
+
check_modifiable(ptr);
|
1288
|
+
olen = RSTRING_LEN(ptr->string);
|
1289
|
+
if (ptr->flags & FMODE_APPEND) {
|
1290
|
+
ptr->pos = olen;
|
1291
|
+
}
|
1292
|
+
if (ptr->pos == olen) {
|
1293
|
+
if (enc == ascii8bit || enc2 == ascii8bit) {
|
1294
|
+
rb_enc_str_buf_cat(ptr->string, RSTRING_PTR(str), len, enc);
|
1295
|
+
OBJ_INFECT(ptr->string, str);
|
1296
|
+
}
|
1297
|
+
else {
|
1298
|
+
rb_str_buf_append(ptr->string, str);
|
1299
|
+
}
|
1300
|
+
}
|
1301
|
+
else {
|
1302
|
+
strio_extend(ptr, ptr->pos, len);
|
1303
|
+
memmove(RSTRING_PTR(ptr->string)+ptr->pos, RSTRING_PTR(str), len);
|
1304
|
+
OBJ_INFECT(ptr->string, str);
|
1305
|
+
}
|
1306
|
+
OBJ_INFECT(ptr->string, self);
|
1307
|
+
RB_GC_GUARD(str);
|
1308
|
+
ptr->pos += len;
|
1309
|
+
return len;
|
1310
|
+
}
|
1311
|
+
|
1312
|
+
/*
|
1313
|
+
* call-seq:
|
1314
|
+
* strio << obj -> strio
|
1315
|
+
*
|
1316
|
+
* See IO#<<.
|
1317
|
+
*/
|
1318
|
+
#define strio_addstr rb_io_addstr
|
1319
|
+
|
1320
|
+
/*
|
1321
|
+
* call-seq:
|
1322
|
+
* strio.print() -> nil
|
1323
|
+
* strio.print(obj, ...) -> nil
|
1324
|
+
*
|
1325
|
+
* See IO#print.
|
1326
|
+
*/
|
1327
|
+
#define strio_print rb_io_print
|
1328
|
+
|
1329
|
+
/*
|
1330
|
+
* call-seq:
|
1331
|
+
* strio.printf(format_string [, obj, ...] ) -> nil
|
1332
|
+
*
|
1333
|
+
* See IO#printf.
|
1334
|
+
*/
|
1335
|
+
#define strio_printf rb_io_printf
|
1336
|
+
|
1337
|
+
/*
|
1338
|
+
* call-seq:
|
1339
|
+
* strio.putc(obj) -> obj
|
1340
|
+
*
|
1341
|
+
* See IO#putc.
|
1342
|
+
*/
|
1343
|
+
static VALUE
|
1344
|
+
strio_putc(VALUE self, VALUE ch)
|
1345
|
+
{
|
1346
|
+
struct StringIO *ptr = writable(self);
|
1347
|
+
VALUE str;
|
1348
|
+
|
1349
|
+
check_modifiable(ptr);
|
1350
|
+
if (RB_TYPE_P(ch, T_STRING)) {
|
1351
|
+
str = rb_str_substr(ch, 0, 1);
|
1352
|
+
}
|
1353
|
+
else {
|
1354
|
+
char c = NUM2CHR(ch);
|
1355
|
+
str = rb_str_new(&c, 1);
|
1356
|
+
}
|
1357
|
+
strio_write(self, str);
|
1358
|
+
return ch;
|
1359
|
+
}
|
1360
|
+
|
1361
|
+
/*
|
1362
|
+
* call-seq:
|
1363
|
+
* strio.puts(obj, ...) -> nil
|
1364
|
+
*
|
1365
|
+
* See IO#puts.
|
1366
|
+
*/
|
1367
|
+
#define strio_puts rb_io_puts
|
1368
|
+
|
1369
|
+
/*
|
1370
|
+
* call-seq:
|
1371
|
+
* strio.read([length [, outbuf]]) -> string, outbuf, or nil
|
1372
|
+
*
|
1373
|
+
* See IO#read.
|
1374
|
+
*/
|
1375
|
+
static VALUE
|
1376
|
+
strio_read(int argc, VALUE *argv, VALUE self)
|
1377
|
+
{
|
1378
|
+
struct StringIO *ptr = readable(self);
|
1379
|
+
VALUE str = Qnil;
|
1380
|
+
long len;
|
1381
|
+
int binary = 0;
|
1382
|
+
|
1383
|
+
rb_check_arity(argc, 0, 2);
|
1384
|
+
switch (argc) {
|
1385
|
+
case 2:
|
1386
|
+
str = argv[1];
|
1387
|
+
if (!NIL_P(str)) {
|
1388
|
+
StringValue(str);
|
1389
|
+
rb_str_modify(str);
|
1390
|
+
}
|
1391
|
+
/* fall through */
|
1392
|
+
case 1:
|
1393
|
+
if (!NIL_P(argv[0])) {
|
1394
|
+
len = NUM2LONG(argv[0]);
|
1395
|
+
if (len < 0) {
|
1396
|
+
rb_raise(rb_eArgError, "negative length %ld given", len);
|
1397
|
+
}
|
1398
|
+
if (len > 0 && ptr->pos >= RSTRING_LEN(ptr->string)) {
|
1399
|
+
if (!NIL_P(str)) rb_str_resize(str, 0);
|
1400
|
+
return Qnil;
|
1401
|
+
}
|
1402
|
+
binary = 1;
|
1403
|
+
break;
|
1404
|
+
}
|
1405
|
+
/* fall through */
|
1406
|
+
case 0:
|
1407
|
+
len = RSTRING_LEN(ptr->string);
|
1408
|
+
if (len <= ptr->pos) {
|
1409
|
+
rb_encoding *enc = binary ? rb_ascii8bit_encoding() : get_enc(ptr);
|
1410
|
+
if (NIL_P(str)) {
|
1411
|
+
str = rb_str_new(0, 0);
|
1412
|
+
}
|
1413
|
+
else {
|
1414
|
+
rb_str_resize(str, 0);
|
1415
|
+
}
|
1416
|
+
rb_enc_associate(str, enc);
|
1417
|
+
return str;
|
1418
|
+
}
|
1419
|
+
else {
|
1420
|
+
len -= ptr->pos;
|
1421
|
+
}
|
1422
|
+
break;
|
1423
|
+
}
|
1424
|
+
if (NIL_P(str)) {
|
1425
|
+
rb_encoding *enc = binary ? rb_ascii8bit_encoding() : get_enc(ptr);
|
1426
|
+
str = strio_substr(ptr, ptr->pos, len, enc);
|
1427
|
+
}
|
1428
|
+
else {
|
1429
|
+
long rest = RSTRING_LEN(ptr->string) - ptr->pos;
|
1430
|
+
if (len > rest) len = rest;
|
1431
|
+
rb_str_resize(str, len);
|
1432
|
+
MEMCPY(RSTRING_PTR(str), RSTRING_PTR(ptr->string) + ptr->pos, char, len);
|
1433
|
+
if (binary)
|
1434
|
+
rb_enc_associate(str, rb_ascii8bit_encoding());
|
1435
|
+
else
|
1436
|
+
rb_enc_copy(str, ptr->string);
|
1437
|
+
}
|
1438
|
+
ptr->pos += RSTRING_LEN(str);
|
1439
|
+
return str;
|
1440
|
+
}
|
1441
|
+
|
1442
|
+
/*
|
1443
|
+
* call-seq:
|
1444
|
+
* strio.sysread(integer[, outbuf]) -> string
|
1445
|
+
* strio.readpartial(integer[, outbuf]) -> string
|
1446
|
+
*
|
1447
|
+
* Similar to #read, but raises +EOFError+ at end of string instead of
|
1448
|
+
* returning +nil+, as well as IO#sysread does.
|
1449
|
+
*/
|
1450
|
+
static VALUE
|
1451
|
+
strio_sysread(int argc, VALUE *argv, VALUE self)
|
1452
|
+
{
|
1453
|
+
VALUE val = rb_funcall2(self, rb_intern("read"), argc, argv);
|
1454
|
+
if (NIL_P(val)) {
|
1455
|
+
rb_eof_error();
|
1456
|
+
}
|
1457
|
+
return val;
|
1458
|
+
}
|
1459
|
+
|
1460
|
+
/*
|
1461
|
+
* call-seq:
|
1462
|
+
* strio.read_nonblock(integer[, outbuf [, opts]]) -> string
|
1463
|
+
*
|
1464
|
+
* Similar to #read, but raises +EOFError+ at end of string unless the
|
1465
|
+
* +exception: false+ option is passed in.
|
1466
|
+
*/
|
1467
|
+
static VALUE
|
1468
|
+
strio_read_nonblock(int argc, VALUE *argv, VALUE self)
|
1469
|
+
{
|
1470
|
+
VALUE opts = Qnil, val;
|
1471
|
+
|
1472
|
+
rb_scan_args(argc, argv, "11:", NULL, NULL, &opts);
|
1473
|
+
|
1474
|
+
if (!NIL_P(opts)) {
|
1475
|
+
argc--;
|
1476
|
+
}
|
1477
|
+
|
1478
|
+
val = strio_read(argc, argv, self);
|
1479
|
+
if (NIL_P(val)) {
|
1480
|
+
if (!NIL_P(opts) &&
|
1481
|
+
rb_hash_lookup2(opts, sym_exception, Qundef) == Qfalse)
|
1482
|
+
return Qnil;
|
1483
|
+
else
|
1484
|
+
rb_eof_error();
|
1485
|
+
}
|
1486
|
+
|
1487
|
+
return val;
|
1488
|
+
}
|
1489
|
+
|
1490
|
+
#define strio_syswrite rb_io_write
|
1491
|
+
|
1492
|
+
static VALUE
|
1493
|
+
strio_syswrite_nonblock(int argc, VALUE *argv, VALUE self)
|
1494
|
+
{
|
1495
|
+
VALUE str;
|
1496
|
+
|
1497
|
+
rb_scan_args(argc, argv, "10:", &str, NULL);
|
1498
|
+
return strio_syswrite(self, str);
|
1499
|
+
}
|
1500
|
+
|
1501
|
+
#define strio_isatty strio_false
|
1502
|
+
|
1503
|
+
#define strio_pid strio_nil
|
1504
|
+
|
1505
|
+
#define strio_fileno strio_nil
|
1506
|
+
|
1507
|
+
/*
|
1508
|
+
* call-seq:
|
1509
|
+
* strio.length -> integer
|
1510
|
+
* strio.size -> integer
|
1511
|
+
*
|
1512
|
+
* Returns the size of the buffer string.
|
1513
|
+
*/
|
1514
|
+
static VALUE
|
1515
|
+
strio_size(VALUE self)
|
1516
|
+
{
|
1517
|
+
VALUE string = StringIO(self)->string;
|
1518
|
+
if (NIL_P(string)) {
|
1519
|
+
rb_raise(rb_eIOError, "not opened");
|
1520
|
+
}
|
1521
|
+
return ULONG2NUM(RSTRING_LEN(string));
|
1522
|
+
}
|
1523
|
+
|
1524
|
+
/*
|
1525
|
+
* call-seq:
|
1526
|
+
* strio.truncate(integer) -> 0
|
1527
|
+
*
|
1528
|
+
* Truncates the buffer string to at most _integer_ bytes. The *strio*
|
1529
|
+
* must be opened for writing.
|
1530
|
+
*/
|
1531
|
+
static VALUE
|
1532
|
+
strio_truncate(VALUE self, VALUE len)
|
1533
|
+
{
|
1534
|
+
VALUE string = writable(self)->string;
|
1535
|
+
long l = NUM2LONG(len);
|
1536
|
+
long plen = RSTRING_LEN(string);
|
1537
|
+
if (l < 0) {
|
1538
|
+
error_inval("negative length");
|
1539
|
+
}
|
1540
|
+
rb_str_resize(string, l);
|
1541
|
+
if (plen < l) {
|
1542
|
+
MEMZERO(RSTRING_PTR(string) + plen, char, l - plen);
|
1543
|
+
}
|
1544
|
+
return len;
|
1545
|
+
}
|
1546
|
+
|
1547
|
+
/*
|
1548
|
+
* call-seq:
|
1549
|
+
* strio.external_encoding => encoding
|
1550
|
+
*
|
1551
|
+
* Returns the Encoding object that represents the encoding of the file.
|
1552
|
+
* If strio is write mode and no encoding is specified, returns <code>nil</code>.
|
1553
|
+
*/
|
1554
|
+
|
1555
|
+
static VALUE
|
1556
|
+
strio_external_encoding(VALUE self)
|
1557
|
+
{
|
1558
|
+
struct StringIO *ptr = StringIO(self);
|
1559
|
+
return rb_enc_from_encoding(get_enc(ptr));
|
1560
|
+
}
|
1561
|
+
|
1562
|
+
/*
|
1563
|
+
* call-seq:
|
1564
|
+
* strio.internal_encoding => encoding
|
1565
|
+
*
|
1566
|
+
* Returns the Encoding of the internal string if conversion is
|
1567
|
+
* specified. Otherwise returns nil.
|
1568
|
+
*/
|
1569
|
+
|
1570
|
+
static VALUE
|
1571
|
+
strio_internal_encoding(VALUE self)
|
1572
|
+
{
|
1573
|
+
return Qnil;
|
1574
|
+
}
|
1575
|
+
|
1576
|
+
/*
|
1577
|
+
* call-seq:
|
1578
|
+
* strio.set_encoding(ext_enc, [int_enc[, opt]]) => strio
|
1579
|
+
*
|
1580
|
+
* Specify the encoding of the StringIO as <i>ext_enc</i>.
|
1581
|
+
* Use the default external encoding if <i>ext_enc</i> is nil.
|
1582
|
+
* 2nd argument <i>int_enc</i> and optional hash <i>opt</i> argument
|
1583
|
+
* are ignored; they are for API compatibility to IO.
|
1584
|
+
*/
|
1585
|
+
|
1586
|
+
static VALUE
|
1587
|
+
strio_set_encoding(int argc, VALUE *argv, VALUE self)
|
1588
|
+
{
|
1589
|
+
rb_encoding* enc;
|
1590
|
+
struct StringIO *ptr = StringIO(self);
|
1591
|
+
VALUE ext_enc, int_enc, opt;
|
1592
|
+
|
1593
|
+
argc = rb_scan_args(argc, argv, "11:", &ext_enc, &int_enc, &opt);
|
1594
|
+
|
1595
|
+
if (NIL_P(ext_enc)) {
|
1596
|
+
enc = rb_default_external_encoding();
|
1597
|
+
}
|
1598
|
+
else {
|
1599
|
+
enc = rb_to_encoding(ext_enc);
|
1600
|
+
}
|
1601
|
+
ptr->enc = enc;
|
1602
|
+
if (WRITABLE(self)) {
|
1603
|
+
rb_enc_associate(ptr->string, enc);
|
1604
|
+
}
|
1605
|
+
|
1606
|
+
return self;
|
1607
|
+
}
|
1608
|
+
|
1609
|
+
/*
|
1610
|
+
* Pseudo I/O on String object.
|
1611
|
+
*
|
1612
|
+
* Commonly used to simulate `$stdio` or `$stderr`
|
1613
|
+
*
|
1614
|
+
* === Examples
|
1615
|
+
*
|
1616
|
+
* require 'stringio'
|
1617
|
+
*
|
1618
|
+
* io = StringIO.new
|
1619
|
+
* io.puts "Hello World"
|
1620
|
+
* io.string #=> "Hello World\n"
|
1621
|
+
*/
|
1622
|
+
void
|
1623
|
+
Init_stringio(void)
|
1624
|
+
{
|
1625
|
+
VALUE StringIO = rb_define_class("StringIO", rb_cData);
|
1626
|
+
|
1627
|
+
rb_include_module(StringIO, rb_mEnumerable);
|
1628
|
+
rb_define_alloc_func(StringIO, strio_s_allocate);
|
1629
|
+
rb_define_singleton_method(StringIO, "new", strio_s_new, -1);
|
1630
|
+
rb_define_singleton_method(StringIO, "open", strio_s_open, -1);
|
1631
|
+
rb_define_method(StringIO, "initialize", strio_initialize, -1);
|
1632
|
+
rb_define_method(StringIO, "initialize_copy", strio_copy, 1);
|
1633
|
+
rb_define_method(StringIO, "reopen", strio_reopen, -1);
|
1634
|
+
|
1635
|
+
rb_define_method(StringIO, "string", strio_get_string, 0);
|
1636
|
+
rb_define_method(StringIO, "string=", strio_set_string, 1);
|
1637
|
+
rb_define_method(StringIO, "lineno", strio_get_lineno, 0);
|
1638
|
+
rb_define_method(StringIO, "lineno=", strio_set_lineno, 1);
|
1639
|
+
|
1640
|
+
|
1641
|
+
/* call-seq: strio.binmode -> true */
|
1642
|
+
rb_define_method(StringIO, "binmode", strio_binmode, 0);
|
1643
|
+
rb_define_method(StringIO, "close", strio_close, 0);
|
1644
|
+
rb_define_method(StringIO, "close_read", strio_close_read, 0);
|
1645
|
+
rb_define_method(StringIO, "close_write", strio_close_write, 0);
|
1646
|
+
rb_define_method(StringIO, "closed?", strio_closed, 0);
|
1647
|
+
rb_define_method(StringIO, "closed_read?", strio_closed_read, 0);
|
1648
|
+
rb_define_method(StringIO, "closed_write?", strio_closed_write, 0);
|
1649
|
+
rb_define_method(StringIO, "eof", strio_eof, 0);
|
1650
|
+
rb_define_method(StringIO, "eof?", strio_eof, 0);
|
1651
|
+
/* call-seq: strio.fcntl */
|
1652
|
+
rb_define_method(StringIO, "fcntl", strio_fcntl, -1);
|
1653
|
+
/* call-seq: strio.flush -> strio */
|
1654
|
+
rb_define_method(StringIO, "flush", strio_flush, 0);
|
1655
|
+
/* call-seq: strio.fsync -> 0 */
|
1656
|
+
rb_define_method(StringIO, "fsync", strio_fsync, 0);
|
1657
|
+
rb_define_method(StringIO, "pos", strio_get_pos, 0);
|
1658
|
+
rb_define_method(StringIO, "pos=", strio_set_pos, 1);
|
1659
|
+
rb_define_method(StringIO, "rewind", strio_rewind, 0);
|
1660
|
+
rb_define_method(StringIO, "seek", strio_seek, -1);
|
1661
|
+
rb_define_method(StringIO, "sync", strio_get_sync, 0);
|
1662
|
+
/* call-seq: strio.sync = boolean -> boolean */
|
1663
|
+
rb_define_method(StringIO, "sync=", strio_set_sync, 1);
|
1664
|
+
rb_define_method(StringIO, "tell", strio_tell, 0);
|
1665
|
+
|
1666
|
+
rb_define_method(StringIO, "each", strio_each, -1);
|
1667
|
+
rb_define_method(StringIO, "each_line", strio_each, -1);
|
1668
|
+
rb_define_method(StringIO, "lines", strio_lines, -1);
|
1669
|
+
rb_define_method(StringIO, "each_byte", strio_each_byte, 0);
|
1670
|
+
rb_define_method(StringIO, "bytes", strio_bytes, 0);
|
1671
|
+
rb_define_method(StringIO, "each_char", strio_each_char, 0);
|
1672
|
+
rb_define_method(StringIO, "chars", strio_chars, 0);
|
1673
|
+
rb_define_method(StringIO, "each_codepoint", strio_each_codepoint, 0);
|
1674
|
+
rb_define_method(StringIO, "codepoints", strio_codepoints, 0);
|
1675
|
+
rb_define_method(StringIO, "getc", strio_getc, 0);
|
1676
|
+
rb_define_method(StringIO, "ungetc", strio_ungetc, 1);
|
1677
|
+
rb_define_method(StringIO, "ungetbyte", strio_ungetbyte, 1);
|
1678
|
+
rb_define_method(StringIO, "getbyte", strio_getbyte, 0);
|
1679
|
+
rb_define_method(StringIO, "gets", strio_gets, -1);
|
1680
|
+
rb_define_method(StringIO, "readlines", strio_readlines, -1);
|
1681
|
+
rb_define_method(StringIO, "read", strio_read, -1);
|
1682
|
+
|
1683
|
+
rb_define_method(StringIO, "write", strio_write_m, -1);
|
1684
|
+
rb_define_method(StringIO, "putc", strio_putc, 1);
|
1685
|
+
|
1686
|
+
/*
|
1687
|
+
* call-seq:
|
1688
|
+
* strio.isatty -> nil
|
1689
|
+
* strio.tty? -> nil
|
1690
|
+
*
|
1691
|
+
*/
|
1692
|
+
rb_define_method(StringIO, "isatty", strio_isatty, 0);
|
1693
|
+
rb_define_method(StringIO, "tty?", strio_isatty, 0);
|
1694
|
+
|
1695
|
+
/* call-seq: strio.pid -> nil */
|
1696
|
+
rb_define_method(StringIO, "pid", strio_pid, 0);
|
1697
|
+
|
1698
|
+
/* call-seq: strio.fileno -> nil */
|
1699
|
+
rb_define_method(StringIO, "fileno", strio_fileno, 0);
|
1700
|
+
rb_define_method(StringIO, "size", strio_size, 0);
|
1701
|
+
rb_define_method(StringIO, "length", strio_size, 0);
|
1702
|
+
rb_define_method(StringIO, "truncate", strio_truncate, 1);
|
1703
|
+
|
1704
|
+
rb_define_method(StringIO, "external_encoding", strio_external_encoding, 0);
|
1705
|
+
rb_define_method(StringIO, "internal_encoding", strio_internal_encoding, 0);
|
1706
|
+
rb_define_method(StringIO, "set_encoding", strio_set_encoding, -1);
|
1707
|
+
|
1708
|
+
{
|
1709
|
+
VALUE mReadable = rb_define_module_under(rb_cIO, "generic_readable");
|
1710
|
+
rb_define_method(mReadable, "readchar", strio_readchar, 0);
|
1711
|
+
rb_define_method(mReadable, "readbyte", strio_readbyte, 0);
|
1712
|
+
rb_define_method(mReadable, "readline", strio_readline, -1);
|
1713
|
+
rb_define_method(mReadable, "sysread", strio_sysread, -1);
|
1714
|
+
rb_define_method(mReadable, "readpartial", strio_sysread, -1);
|
1715
|
+
rb_define_method(mReadable, "read_nonblock", strio_read_nonblock, -1);
|
1716
|
+
rb_include_module(StringIO, mReadable);
|
1717
|
+
}
|
1718
|
+
{
|
1719
|
+
VALUE mWritable = rb_define_module_under(rb_cIO, "generic_writable");
|
1720
|
+
rb_define_method(mWritable, "<<", strio_addstr, 1);
|
1721
|
+
rb_define_method(mWritable, "print", strio_print, -1);
|
1722
|
+
rb_define_method(mWritable, "printf", strio_printf, -1);
|
1723
|
+
rb_define_method(mWritable, "puts", strio_puts, -1);
|
1724
|
+
rb_define_method(mWritable, "syswrite", strio_syswrite, 1);
|
1725
|
+
rb_define_method(mWritable, "write_nonblock", strio_syswrite_nonblock, -1);
|
1726
|
+
rb_include_module(StringIO, mWritable);
|
1727
|
+
}
|
1728
|
+
|
1729
|
+
sym_exception = ID2SYM(rb_intern("exception"));
|
1730
|
+
}
|