cybrid_api_id_ruby 0.6.1 → 0.6.2

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