mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* ext/iconv/iconv.c (iconv_create): strips glibc style option before
charset mapping. retris without options if they seemed causing error, and warns. [ruby-dev:36147] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@19147 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
f0bf74a07b
commit
07e08245d3
2 changed files with 74 additions and 13 deletions
|
@ -1,3 +1,9 @@
|
|||
Fri Sep 5 18:16:31 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||
|
||||
* ext/iconv/iconv.c (iconv_create): strips glibc style option before
|
||||
charset mapping. retris without options if they seemed causing
|
||||
error, and warns. [ruby-dev:36147]
|
||||
|
||||
Fri Sep 5 03:09:48 2008 Koichi Sasada <ko1@atdot.net>
|
||||
|
||||
* iseq.c (iseq_data_to_ary): make it static.
|
||||
|
|
|
@ -135,6 +135,21 @@ charset_map_get(void)
|
|||
return charset_map;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
strip_glibc_option(VALUE *code)
|
||||
{
|
||||
VALUE val = *code;
|
||||
const char *ptr = RSTRING_PTR(val), *pend = RSTRING_END(val);
|
||||
const char *slash = memchr(ptr, '/', pend - ptr);
|
||||
if (slash && slash < pend - 1 && slash[1] == '/') {
|
||||
VALUE opt = rb_str_subseq(val, slash - ptr, pend - slash);
|
||||
val = rb_str_subseq(val, 0, slash - ptr);
|
||||
*code = val;
|
||||
return opt;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char *
|
||||
map_charset(VALUE *code)
|
||||
{
|
||||
|
@ -153,29 +168,53 @@ map_charset(VALUE *code)
|
|||
static iconv_t
|
||||
iconv_create(VALUE to, VALUE from, struct rb_iconv_opt_t *opt, int *idx)
|
||||
{
|
||||
VALUE toopt = strip_glibc_option(&to);
|
||||
VALUE fromopt = strip_glibc_option(&from);
|
||||
VALUE toenc = 0, fromenc = 0;
|
||||
const char* tocode = map_charset(&to);
|
||||
const char* fromcode = map_charset(&from);
|
||||
iconv_t cd;
|
||||
int retry = 0;
|
||||
|
||||
if ((*idx = rb_enc_find_index(tocode)) < 0) {
|
||||
const char *slash = strchr(tocode, '/');
|
||||
if (slash && slash[1] == '/') {
|
||||
VALUE tmp = rb_str_new(tocode, slash - tocode);
|
||||
*idx = rb_enc_find_index(RSTRING_PTR(tmp));
|
||||
}
|
||||
*idx = rb_enc_find_index(tocode);
|
||||
|
||||
if (toopt) {
|
||||
toenc = rb_str_plus(to, toopt);
|
||||
tocode = RSTRING_PTR(toenc);
|
||||
}
|
||||
|
||||
cd = iconv_open(tocode, fromcode);
|
||||
if (cd == (iconv_t)-1) {
|
||||
if (fromopt) {
|
||||
fromenc = rb_str_plus(from, fromopt);
|
||||
fromcode = RSTRING_PTR(fromenc);
|
||||
}
|
||||
while ((cd = iconv_open(tocode, fromcode)) == (iconv_t)-1) {
|
||||
int inval = 0;
|
||||
switch (errno) {
|
||||
case EMFILE:
|
||||
case ENFILE:
|
||||
case ENOMEM:
|
||||
rb_gc();
|
||||
cd = iconv_open(tocode, fromcode);
|
||||
if (!retry++) {
|
||||
rb_gc();
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case EINVAL:
|
||||
retry = 0;
|
||||
inval = 1;
|
||||
if (toenc) {
|
||||
tocode = RSTRING_PTR(to);
|
||||
rb_str_resize(toenc, 0);
|
||||
toenc = 0;
|
||||
continue;
|
||||
}
|
||||
if (fromenc) {
|
||||
fromcode = RSTRING_PTR(from);
|
||||
rb_str_resize(fromenc, 0);
|
||||
fromenc = 0;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (cd == (iconv_t)-1) {
|
||||
int inval = errno == EINVAL;
|
||||
{
|
||||
const char *s = inval ? "invalid encoding " : "iconv";
|
||||
volatile VALUE msg = rb_str_new(0, strlen(s) + RSTRING_LEN(to) +
|
||||
RSTRING_LEN(from) + 8);
|
||||
|
@ -190,10 +229,25 @@ iconv_create(VALUE to, VALUE from, struct rb_iconv_opt_t *opt, int *idx)
|
|||
}
|
||||
}
|
||||
|
||||
if (toopt || fromopt) {
|
||||
if (toopt && fromopt && RTEST(rb_str_equal(toopt, fromopt))) {
|
||||
fromopt = 0;
|
||||
}
|
||||
if (toopt && fromopt) {
|
||||
rb_warning("encoding option isn't portable: %s, %s",
|
||||
RSTRING_PTR(toopt) + 2, RSTRING_PTR(fromopt) + 2);
|
||||
}
|
||||
else {
|
||||
rb_warning("encoding option isn't portable: %s",
|
||||
(toopt ? RSTRING_PTR(toopt) : RSTRING_PTR(fromopt)) + 2);
|
||||
}
|
||||
}
|
||||
|
||||
if (opt) {
|
||||
#ifdef ICONV_SET_TRANSLITERATE
|
||||
if (opt->transliterate != Qundef) {
|
||||
int flag = RTEST(opt->transliterate);
|
||||
rb_warning("encoding option isn't portable: transliterate");
|
||||
if (iconvctl(cd, ICONV_SET_TRANSLITERATE, (void *)&flag))
|
||||
rb_sys_fail("ICONV_SET_TRANSLITERATE");
|
||||
}
|
||||
|
@ -201,6 +255,7 @@ iconv_create(VALUE to, VALUE from, struct rb_iconv_opt_t *opt, int *idx)
|
|||
#ifdef ICONV_SET_DISCARD_ILSEQ
|
||||
if (opt->discard_ilseq != Qundef) {
|
||||
int flag = RTEST(opt->discard_ilseq);
|
||||
rb_warning("encoding option isn't portable: discard_ilseq");
|
||||
if (iconvctl(cd, ICONV_SET_DISCARD_ILSEQ, (void *)&flag))
|
||||
rb_sys_fail("ICONV_SET_DISCARD_ILSEQ");
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue