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;
|
||
|
}
|
||