Project

General

Profile

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

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

View differences:

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;
}
    (1-1/1)