Bug #8445 » support-fallback-for-io.patch
| transcode.c (作業コピー) | ||
|---|---|---|
| 
             size_t readagain_len; 
   | 
||
| 
         } last_error; 
   | 
||
| 
         VALUE fallback; 
   | 
||
| 
         VALUE (*fallback_func)(VALUE, VALUE); 
   | 
||
| 
         /* The following fields are only for Encoding::Converter. 
   | 
||
| 
          * rb_econv_open set them NULL. */ 
   | 
||
| 
         rb_encoding *source_encoding; 
   | 
||
| 
         rb_encoding *destination_encoding; 
   | 
||
| 
     }; 
   | 
||
| 
     /* 
   | 
||
| ... | ... | |
| 
         ec->last_error.readagain_len = 0; 
   | 
||
| 
         ec->source_encoding = NULL; 
   | 
||
| 
         ec->destination_encoding = NULL; 
   | 
||
| 
         ec->fallback = Qnil; 
   | 
||
| 
         ec->fallback_func = 0; 
   | 
||
| 
         return ec; 
   | 
||
| 
     } 
   | 
||
| ... | ... | |
| 
       resume: 
   | 
||
| 
         ret = rb_econv_convert0(ec, input_ptr, input_stop, output_ptr, output_stop, flags); 
   | 
||
| 
         if (!NIL_P(ec->fallback) && ret == econv_undefined_conversion) { 
   | 
||
| 
     	VALUE rep = rb_enc_str_new( 
   | 
||
| 
     		(const char *)ec->last_error.error_bytes_start, 
   | 
||
| 
     		ec->last_error.error_bytes_len, 
   | 
||
| 
     		rb_enc_find(ec->last_error.source_encoding)); 
   | 
||
| 
     	rep = (*(ec->fallback_func))(ec->fallback, rep); 
   | 
||
| 
     	if (rep != Qundef && !NIL_P(rep)) { 
   | 
||
| 
     	    StringValue(rep); 
   | 
||
| 
     	    ret = rb_econv_insert_output(ec, (const unsigned char *)RSTRING_PTR(rep), 
   | 
||
| 
     		    RSTRING_LEN(rep), rb_enc_name(rb_enc_get(rep))); 
   | 
||
| 
     	    if ((int)ret == -1) { 
   | 
||
| 
     		rb_raise(rb_eArgError, "too big fallback string"); 
   | 
||
| 
     	    } 
   | 
||
| 
     	    goto resume; 
   | 
||
| 
     	} 
   | 
||
| 
         } 
   | 
||
| 
         if (ret == econv_invalid_byte_sequence || 
   | 
||
| 
             ret == econv_incomplete_input) { 
   | 
||
| 
     	/* deal with invalid byte sequence */ 
   | 
||
| ... | ... | |
| 
         unsigned char *out_start = *out_pos; 
   | 
||
| 
         int max_output; 
   | 
||
| 
         VALUE exc; 
   | 
||
| 
         VALUE fallback = Qnil; 
   | 
||
| 
         VALUE (*fallback_func)(VALUE, VALUE) = 0; 
   | 
||
| 
         ec = rb_econv_open_opts(src_encoding, dst_encoding, ecflags, ecopts); 
   | 
||
| 
         if (!ec) 
   | 
||
| 
             rb_exc_raise(rb_econv_open_exc(src_encoding, dst_encoding, ecflags)); 
   | 
||
| 
         if (!NIL_P(ecopts) && RB_TYPE_P(ecopts, T_HASH)) { 
   | 
||
| 
     	fallback = rb_hash_aref(ecopts, sym_fallback); 
   | 
||
| 
     	if (RB_TYPE_P(fallback, T_HASH)) { 
   | 
||
| 
     	    fallback_func = hash_fallback; 
   | 
||
| 
     	} 
   | 
||
| 
     	else if (rb_obj_is_proc(fallback)) { 
   | 
||
| 
     	    fallback_func = proc_fallback; 
   | 
||
| 
     	} 
   | 
||
| 
     	else if (rb_obj_is_method(fallback)) { 
   | 
||
| 
     	    fallback_func = method_fallback; 
   | 
||
| 
     	} 
   | 
||
| 
     	else { 
   | 
||
| 
     	    fallback_func = aref_fallback; 
   | 
||
| 
     	} 
   | 
||
| 
         } 
   | 
||
| 
         last_tc = ec->last_tc; 
   | 
||
| 
         max_output = last_tc ? last_tc->transcoder->max_output : 1; 
   | 
||
| 
       resume: 
   | 
||
| 
         ret = rb_econv_convert(ec, in_pos, in_stop, out_pos, out_stop, 0); 
   | 
||
| 
         if (!NIL_P(fallback) && ret == econv_undefined_conversion) { 
   | 
||
| 
     	VALUE rep = rb_enc_str_new( 
   | 
||
| 
     		(const char *)ec->last_error.error_bytes_start, 
   | 
||
| 
     		ec->last_error.error_bytes_len, 
   | 
||
| 
     		rb_enc_find(ec->last_error.source_encoding)); 
   | 
||
| 
     	rep = (*fallback_func)(fallback, rep); 
   | 
||
| 
     	if (rep != Qundef && !NIL_P(rep)) { 
   | 
||
| 
     	    StringValue(rep); 
   | 
||
| 
     	    ret = rb_econv_insert_output(ec, (const unsigned char *)RSTRING_PTR(rep), 
   | 
||
| 
     		    RSTRING_LEN(rep), rb_enc_name(rb_enc_get(rep))); 
   | 
||
| 
     	    if ((int)ret == -1) { 
   | 
||
| 
     		rb_raise(rb_eArgError, "too big fallback string"); 
   | 
||
| 
     	    } 
   | 
||
| 
     	    goto resume; 
   | 
||
| 
     	} 
   | 
||
| 
         } 
   | 
||
| 
         if (ret == econv_invalid_byte_sequence || 
   | 
||
| 
             ret == econv_incomplete_input || 
   | 
||
| 
             ret == econv_undefined_conversion) { 
   | 
||
| ... | ... | |
| 
     { 
   | 
||
| 
         rb_econv_t *ec; 
   | 
||
| 
         VALUE replacement; 
   | 
||
| 
         VALUE fallback = Qnil; 
   | 
||
| 
         VALUE (*fallback_func)(VALUE, VALUE) = 0; 
   | 
||
| 
         if (NIL_P(opthash)) { 
   | 
||
| 
             replacement = Qnil; 
   | 
||
| ... | ... | |
| 
                 return NULL; 
   | 
||
| 
             } 
   | 
||
| 
         } 
   | 
||
| 
         if (!NIL_P(opthash) && RB_TYPE_P(opthash, T_HASH)) { 
   | 
||
| 
     	fallback = rb_hash_aref(opthash, sym_fallback); 
   | 
||
| 
     	if (RB_TYPE_P(fallback, T_HASH)) { 
   | 
||
| 
     	    fallback_func = hash_fallback; 
   | 
||
| 
     	} 
   | 
||
| 
     	else if (rb_obj_is_proc(fallback)) { 
   | 
||
| 
     	    fallback_func = proc_fallback; 
   | 
||
| 
     	} 
   | 
||
| 
     	else if (rb_obj_is_method(fallback)) { 
   | 
||
| 
     	    fallback_func = method_fallback; 
   | 
||
| 
     	} 
   | 
||
| 
     	else { 
   | 
||
| 
     	    fallback_func = aref_fallback; 
   | 
||
| 
     	} 
   | 
||
| 
             ec->fallback = fallback; 
   | 
||
| 
             ec->fallback_func = fallback_func; 
   | 
||
| 
         } 
   | 
||
| 
         return ec; 
   | 
||
| 
     } 
   | 
||