Project

General

Profile

Bug #8445 » support-fallback-for-io.patch

pjmtdw (Haruhiro Yoshimoto), 05/24/2013 10:03 PM

View differences:

transcode.c (作業コピー)
141 141
        size_t readagain_len;
142 142
    } last_error;
143 143

  
144
    VALUE fallback;
145
    VALUE (*fallback_func)(VALUE, VALUE);
146

  
144 147
    /* The following fields are only for Encoding::Converter.
145 148
     * rb_econv_open set them NULL. */
146 149
    rb_encoding *source_encoding;
147 150
    rb_encoding *destination_encoding;
151

  
148 152
};
149 153

  
150 154
/*
......
887 891
    ec->last_error.readagain_len = 0;
888 892
    ec->source_encoding = NULL;
889 893
    ec->destination_encoding = NULL;
894

  
895
    ec->fallback = Qnil;
896
    ec->fallback_func = 0;
890 897
    return ec;
891 898
}
892 899

  
......
1468 1475
  resume:
1469 1476
    ret = rb_econv_convert0(ec, input_ptr, input_stop, output_ptr, output_stop, flags);
1470 1477

  
1478
    if (!NIL_P(ec->fallback) && ret == econv_undefined_conversion) {
1479
	VALUE rep = rb_enc_str_new(
1480
		(const char *)ec->last_error.error_bytes_start,
1481
		ec->last_error.error_bytes_len,
1482
		rb_enc_find(ec->last_error.source_encoding));
1483
	rep = (*(ec->fallback_func))(ec->fallback, rep);
1484
	if (rep != Qundef && !NIL_P(rep)) {
1485
	    StringValue(rep);
1486
	    ret = rb_econv_insert_output(ec, (const unsigned char *)RSTRING_PTR(rep),
1487
		    RSTRING_LEN(rep), rb_enc_name(rb_enc_get(rep)));
1488
	    if ((int)ret == -1) {
1489
		rb_raise(rb_eArgError, "too big fallback string");
1490
	    }
1491
	    goto resume;
1492
	}
1493
    }
1494

  
1471 1495
    if (ret == econv_invalid_byte_sequence ||
1472 1496
        ret == econv_incomplete_input) {
1473 1497
	/* deal with invalid byte sequence */
......
2270 2294
    unsigned char *out_start = *out_pos;
2271 2295
    int max_output;
2272 2296
    VALUE exc;
2273
    VALUE fallback = Qnil;
2274
    VALUE (*fallback_func)(VALUE, VALUE) = 0;
2275 2297

  
2276 2298
    ec = rb_econv_open_opts(src_encoding, dst_encoding, ecflags, ecopts);
2277 2299
    if (!ec)
2278 2300
        rb_exc_raise(rb_econv_open_exc(src_encoding, dst_encoding, ecflags));
2279 2301

  
2280
    if (!NIL_P(ecopts) && RB_TYPE_P(ecopts, T_HASH)) {
2281
	fallback = rb_hash_aref(ecopts, sym_fallback);
2282
	if (RB_TYPE_P(fallback, T_HASH)) {
2283
	    fallback_func = hash_fallback;
2284
	}
2285
	else if (rb_obj_is_proc(fallback)) {
2286
	    fallback_func = proc_fallback;
2287
	}
2288
	else if (rb_obj_is_method(fallback)) {
2289
	    fallback_func = method_fallback;
2290
	}
2291
	else {
2292
	    fallback_func = aref_fallback;
2293
	}
2294
    }
2295 2302
    last_tc = ec->last_tc;
2296 2303
    max_output = last_tc ? last_tc->transcoder->max_output : 1;
2297 2304

  
2298 2305
  resume:
2299 2306
    ret = rb_econv_convert(ec, in_pos, in_stop, out_pos, out_stop, 0);
2300 2307

  
2301
    if (!NIL_P(fallback) && ret == econv_undefined_conversion) {
2302
	VALUE rep = rb_enc_str_new(
2303
		(const char *)ec->last_error.error_bytes_start,
2304
		ec->last_error.error_bytes_len,
2305
		rb_enc_find(ec->last_error.source_encoding));
2306
	rep = (*fallback_func)(fallback, rep);
2307
	if (rep != Qundef && !NIL_P(rep)) {
2308
	    StringValue(rep);
2309
	    ret = rb_econv_insert_output(ec, (const unsigned char *)RSTRING_PTR(rep),
2310
		    RSTRING_LEN(rep), rb_enc_name(rb_enc_get(rep)));
2311
	    if ((int)ret == -1) {
2312
		rb_raise(rb_eArgError, "too big fallback string");
2313
	    }
2314
	    goto resume;
2315
	}
2316
    }
2317

  
2318 2308
    if (ret == econv_invalid_byte_sequence ||
2319 2309
        ret == econv_incomplete_input ||
2320 2310
        ret == econv_undefined_conversion) {
......
2571 2561
{
2572 2562
    rb_econv_t *ec;
2573 2563
    VALUE replacement;
2564
    VALUE fallback = Qnil;
2565
    VALUE (*fallback_func)(VALUE, VALUE) = 0;
2574 2566

  
2575 2567
    if (NIL_P(opthash)) {
2576 2568
        replacement = Qnil;
......
2598 2590
            return NULL;
2599 2591
        }
2600 2592
    }
2593
    if (!NIL_P(opthash) && RB_TYPE_P(opthash, T_HASH)) {
2594
	fallback = rb_hash_aref(opthash, sym_fallback);
2595
	if (RB_TYPE_P(fallback, T_HASH)) {
2596
	    fallback_func = hash_fallback;
2597
	}
2598
	else if (rb_obj_is_proc(fallback)) {
2599
	    fallback_func = proc_fallback;
2600
	}
2601
	else if (rb_obj_is_method(fallback)) {
2602
	    fallback_func = method_fallback;
2603
	}
2604
	else {
2605
	    fallback_func = aref_fallback;
2606
	}
2607
        ec->fallback = fallback;
2608
        ec->fallback_func = fallback_func;
2609
    }
2601 2610
    return ec;
2602 2611
}
2603 2612