18 #define ENABLE_ECONV_NEWLINE_OPTION 1
32 #ifdef ENABLE_ECONV_NEWLINE_OPTION
45 static unsigned char *
47 const unsigned char *str,
size_t len,
48 unsigned char *caller_dst_buf,
size_t caller_dst_bufsize,
80 char ary[
sizeof(double) >
sizeof(
void*) ?
sizeof(double) :
sizeof(
void*)];
84 #define TRANSCODING_READBUF(tc) \
85 ((tc)->transcoder->max_input <= (int)sizeof((tc)->readbuf.ary) ? \
88 #define TRANSCODING_WRITEBUF(tc) \
89 ((tc)->transcoder->max_output <= (int)sizeof((tc)->writebuf.ary) ? \
90 (tc)->writebuf.ary : \
92 #define TRANSCODING_WRITEBUF_SIZE(tc) \
93 ((tc)->transcoder->max_output <= (int)sizeof((tc)->writebuf.ary) ? \
94 sizeof((tc)->writebuf.ary) : \
95 (size_t)(tc)->transcoder->max_output)
96 #define TRANSCODING_STATE_EMBED_MAX ((int)sizeof(union rb_transcoding_state_t))
97 #define TRANSCODING_STATE(tc) \
98 ((tc)->transcoder->state_size <= (int)sizeof((tc)->state) ? \
154 #define DECORATOR_P(sname, dname) (*(sname) == '\0')
178 entry->
sname = sname;
179 entry->
dname = dname;
241 #define encoding_equal(enc1, enc2) (STRCASECMP((enc1), (enc2)) == 0)
258 const char *dname = (
const char *)key;
278 void (*
callback)(
const char *sname,
const char *dname,
int depth,
void *
arg),
335 const char *enc = dname;
343 enc = (
const char *)val;
351 callback((
const char *)val, enc, --depth, arg);
352 enc = (
const char *)val;
368 const char *
const lib = entry->
lib;
369 const size_t len =
strlen(lib);
377 memcpy(path, transcoder_lib_prefix,
sizeof(transcoder_lib_prefix) - 1);
378 memcpy(path +
sizeof(transcoder_lib_prefix) - 1, lib, len);
397 *repl_encname_ptr =
"UTF-8";
398 return "\xEF\xBF\xBD";
402 *repl_encname_ptr =
"US-ASCII";
411 static const unsigned char *
413 const unsigned char *in_start,
414 const unsigned char *inchar_start,
415 const unsigned char *in_p,
416 size_t *char_len_ptr)
418 const unsigned char *ptr;
419 if (inchar_start - in_start < tc->recognized_len) {
421 inchar_start,
unsigned char, in_p - inchar_start);
433 const unsigned char *in_stop,
unsigned char *out_stop,
439 ssize_t readagain_len = 0;
441 const unsigned char *inchar_start;
442 const unsigned char *in_p;
444 unsigned char *out_p;
446 in_p = inchar_start = *in_pos;
450 #define SUSPEND(ret, num) \
452 tc->resume_position = (num); \
453 if (0 < in_p - inchar_start) \
454 MEMMOVE(TRANSCODING_READBUF(tc)+tc->recognized_len, \
455 inchar_start, unsigned char, in_p - inchar_start); \
458 tc->recognized_len += in_p - inchar_start; \
459 if (readagain_len) { \
460 tc->recognized_len -= readagain_len; \
461 tc->readagain_len = readagain_len; \
464 resume_label ## num:; \
466 #define SUSPEND_OBUF(num) \
468 while (out_stop - out_p < 1) { SUSPEND(econv_destination_buffer_full, num); } \
471 #define SUSPEND_AFTER_OUTPUT(num) \
472 if ((opt & ECONV_AFTER_OUTPUT) && *out_pos != out_p) { \
473 SUSPEND(econv_after_output, num); \
476 #define next_table (tc->next_table)
477 #define next_info (tc->next_info)
478 #define next_byte (tc->next_byte)
479 #define writebuf_len (tc->writebuf_len)
480 #define writebuf_off (tc->writebuf_off)
484 case 1:
goto resume_label1;
485 case 2:
goto resume_label2;
486 case 3:
goto resume_label3;
487 case 4:
goto resume_label4;
488 case 5:
goto resume_label5;
489 case 6:
goto resume_label6;
490 case 7:
goto resume_label7;
491 case 8:
goto resume_label8;
492 case 9:
goto resume_label9;
493 case 10:
goto resume_label10;
494 case 11:
goto resume_label11;
495 case 12:
goto resume_label12;
496 case 13:
goto resume_label13;
497 case 14:
goto resume_label14;
498 case 15:
goto resume_label15;
499 case 16:
goto resume_label16;
500 case 17:
goto resume_label17;
501 case 18:
goto resume_label18;
502 case 19:
goto resume_label19;
503 case 20:
goto resume_label20;
504 case 21:
goto resume_label21;
505 case 22:
goto resume_label22;
506 case 23:
goto resume_label23;
507 case 24:
goto resume_label24;
508 case 25:
goto resume_label25;
509 case 26:
goto resume_label26;
510 case 27:
goto resume_label27;
511 case 28:
goto resume_label28;
512 case 29:
goto resume_label29;
513 case 30:
goto resume_label30;
514 case 31:
goto resume_label31;
515 case 32:
goto resume_label32;
516 case 33:
goto resume_label33;
517 case 34:
goto resume_label34;
527 if (in_stop <= in_p) {
534 #define BYTE_ADDR(index) (tr->byte_array + (index))
535 #define WORD_ADDR(index) (tr->word_array + INFO2WORDINDEX(index))
536 #define BL_BASE BYTE_ADDR(BYTE_LOOKUP_BASE(WORD_ADDR(next_table)))
537 #define BL_INFO WORD_ADDR(BYTE_LOOKUP_INFO(WORD_ADDR(next_table)))
538 #define BL_MIN_BYTE (BL_BASE[0])
539 #define BL_MAX_BYTE (BL_BASE[1])
540 #define BL_OFFSET(byte) (BL_BASE[2+(byte)-BL_MIN_BYTE])
541 #define BL_ACTION(byte) (BL_INFO[BL_OFFSET((byte))])
554 const unsigned char *p = inchar_start;
567 case 0x00:
case 0x04:
case 0x08:
case 0x0C:
568 case 0x10:
case 0x14:
case 0x18:
case 0x1C:
570 while (in_p >= in_stop) {
616 const unsigned char *char_start;
640 const unsigned char *char_start;
646 char_start, (
size_t)char_len,
647 out_p, out_stop - out_p);
652 char_start, (
size_t)char_len,
664 const unsigned char *char_start;
671 out_p, out_stop - out_p);
705 discard_len = ((invalid_len - 1) / unitlen) * unitlen;
706 readagain_len = invalid_len - discard_len;
734 out_p, out_stop - out_p);
758 const unsigned char *in_stop,
unsigned char *out_stop,
764 const unsigned char *readagain_pos = readagain_buf;
765 const unsigned char *readagain_stop = readagain_buf + tc->
readagain_len;
774 readagain_pos,
unsigned char, readagain_stop - readagain_pos);
790 if (TRANSCODING_STATE_EMBED_MAX < tr->state_size)
811 const unsigned char **input_ptr,
const unsigned char *input_stop,
812 unsigned char **output_ptr,
unsigned char *output_stop,
816 input_ptr, output_ptr,
817 input_stop, output_stop,
828 if (TRANSCODING_STATE_EMBED_MAX < tr->state_size)
843 if (TRANSCODING_STATE_EMBED_MAX < tr->state_size) {
938 for (i = 0; i < n; i++) {
947 for (i = 0; i < n; i++) {
998 if (*sname ==
'\0' && *dname ==
'\0') {
1008 if (num_trans < 0) {
1019 ec->
flags = ecflags;
1026 #define MAX_ECFLAGS_DECORATORS 32
1049 if (ecflags & ECONV_XML_TEXT_DECORATOR)
1050 decorators_ret[num_decorators++] =
"xml_text_escape";
1051 if (ecflags & ECONV_XML_ATTR_CONTENT_DECORATOR)
1052 decorators_ret[num_decorators++] =
"xml_attr_content_escape";
1054 decorators_ret[num_decorators++] =
"xml_attr_quote";
1057 decorators_ret[num_decorators++] =
"crlf_newline";
1059 decorators_ret[num_decorators++] =
"cr_newline";
1061 decorators_ret[num_decorators++] =
"universal_newline";
1063 return num_decorators;
1075 if (num_decorators == -1)
1082 for (i = 0; i < num_decorators; i++)
1088 ec->
flags |= ecflags & ~ECONV_ERROR_HANDLER_MASK;
1095 const unsigned char **input_ptr,
const unsigned char *input_stop,
1096 unsigned char **output_ptr,
unsigned char *output_stop,
1103 const unsigned char **ipp, *is, *iold;
1104 unsigned char **opp, *os, *oold;
1110 for (i = start; i < ec->
num_trans; i++) {
1144 flags &= ~ECONV_AFTER_OUTPUT;
1147 f &= ~ECONV_AFTER_OUTPUT;
1151 if (iold != *ipp || oold != *opp)
1176 const unsigned char **input_ptr,
const unsigned char *input_stop,
1177 unsigned char **output_ptr,
unsigned char *output_stop,
1179 int *result_position_ptr)
1182 int needreport_index;
1185 unsigned char empty_buf;
1186 unsigned char *empty_ptr = &empty_buf;
1189 input_ptr = (
const unsigned char **)&empty_ptr;
1190 input_stop = empty_ptr;
1194 output_ptr = &empty_ptr;
1195 output_stop = empty_ptr;
1201 needreport_index = -1;
1202 for (i = ec->
num_trans-1; 0 <= i; i--) {
1210 needreport_index = i;
1211 goto found_needreport;
1218 rb_bug(
"unexpected transcode last result");
1230 result_position_ptr);
1242 needreport_index =
trans_sweep(ec, input_ptr, input_stop, output_ptr, output_stop, flags, sweep_start);
1243 sweep_start = needreport_index + 1;
1244 }
while (needreport_index != -1 && needreport_index != ec->
num_trans-1);
1246 for (i = ec->
num_trans-1; 0 <= i; i--) {
1255 if (result_position_ptr)
1256 *result_position_ptr = i;
1260 if (result_position_ptr)
1261 *result_position_ptr = -1;
1267 const unsigned char **input_ptr,
const unsigned char *input_stop,
1268 unsigned char **output_ptr,
unsigned char *output_stop,
1272 int result_position;
1280 if (output_stop - *output_ptr < ec->in_data_end - ec->
in_data_start) {
1281 len = output_stop - *output_ptr;
1283 *output_ptr = output_stop;
1297 if (output_stop - *output_ptr < input_stop - *input_ptr) {
1298 len = output_stop - *output_ptr;
1301 len = input_stop - *input_ptr;
1304 *(*output_ptr)++ = *(*input_ptr)++;
1308 memcpy(*output_ptr, *input_ptr, len);
1311 if (*input_ptr != input_stop)
1323 if (data_start != data_end) {
1325 if (output_stop - *output_ptr < data_end - data_start) {
1326 len = output_stop - *output_ptr;
1327 memcpy(*output_ptr, data_start, len);
1328 *output_ptr = output_stop;
1333 len = data_end - data_start;
1334 memcpy(*output_ptr, data_start, len);
1353 *input_ptr != input_stop) {
1354 input_stop = *input_ptr;
1355 res =
rb_trans_conv(ec, input_ptr, input_stop, output_ptr, output_stop, flags, &result_position);
1359 else if ((flags & ECONV_AFTER_OUTPUT) ||
1361 res =
rb_trans_conv(ec, input_ptr, input_stop, output_ptr, output_stop, flags, &result_position);
1364 flags |= ECONV_AFTER_OUTPUT;
1366 res =
rb_trans_conv(ec, input_ptr, input_stop, output_ptr, output_stop, flags, &result_position);
1393 unsigned char utfbuf[1024];
1394 const unsigned char *utf;
1396 int utf_allocated = 0;
1397 char charef_buf[16];
1398 const unsigned char *p;
1407 utfbuf,
sizeof(utfbuf),
1415 if (utf_len % 4 != 0)
1419 while (4 <= utf_len) {
1425 snprintf(charef_buf,
sizeof(charef_buf),
"&#x%X;", u);
1447 const unsigned char **input_ptr,
const unsigned char *input_stop,
1448 unsigned char **output_ptr,
unsigned char *output_stop,
1453 unsigned char empty_buf;
1454 unsigned char *empty_ptr = &empty_buf;
1459 input_ptr = (
const unsigned char **)&empty_ptr;
1460 input_stop = empty_ptr;
1464 output_ptr = &empty_ptr;
1465 output_stop = empty_ptr;
1469 ret =
rb_econv_convert0(ec, input_ptr, input_stop, output_ptr, output_stop, flags);
1518 static unsigned char *
1520 const unsigned char *str,
size_t len,
1521 unsigned char *caller_dst_buf,
size_t caller_dst_bufsize,
1522 size_t *dst_len_ptr)
1524 unsigned char *dst_str;
1531 const unsigned char *sp;
1535 dst_bufsize = caller_dst_bufsize;
1545 dst_str = caller_dst_buf;
1547 dst_str =
xmalloc(dst_bufsize);
1550 dp = dst_str+dst_len;
1552 dst_len = dp - dst_str;
1558 if (dst_str == caller_dst_buf) {
1561 memcpy(tmp, dst_str, dst_bufsize/2);
1565 dst_str =
xrealloc(dst_str, dst_bufsize);
1567 dp = dst_str+dst_len;
1569 dst_len = dp - dst_str;
1575 *dst_len_ptr = dst_len;
1579 if (dst_str != caller_dst_buf)
1588 const unsigned char *str,
size_t len,
const char *str_encoding)
1591 unsigned char insert_buf[4096];
1592 const unsigned char *insert_str =
NULL;
1595 int last_trans_index;
1598 unsigned char **buf_start_p;
1599 unsigned char **data_start_p;
1600 unsigned char **data_end_p;
1601 unsigned char **buf_end_p;
1616 str, len, insert_buf,
sizeof(insert_buf), &insert_len);
1617 if (insert_str ==
NULL)
1632 tc = ec->
elems[last_trans_index].
tc;
1634 if (need < insert_len)
1636 if (last_trans_index == 0) {
1656 tc = ec->
elems[last_trans_index].
tc;
1659 if (*buf_start_p ==
NULL) {
1662 *data_start_p =
buf;
1664 *buf_end_p = buf+need;
1666 else if ((
size_t)(*buf_end_p - *data_end_p) < need) {
1667 MEMMOVE(*buf_start_p, *data_start_p,
unsigned char, *data_end_p - *data_start_p);
1668 *data_end_p = *buf_start_p + (*data_end_p - *data_start_p);
1669 *data_start_p = *buf_start_p;
1670 if ((
size_t)(*buf_end_p - *data_end_p) < need) {
1672 size_t s = (*data_end_p - *buf_start_p) + need;
1676 *data_start_p =
buf;
1677 *data_end_p = buf + (*data_end_p - *buf_start_p);
1679 *buf_end_p = buf + s;
1683 memcpy(*data_end_p, insert_str, insert_len);
1684 *data_end_p += insert_len;
1691 if (insert_str != str && insert_str != insert_buf)
1692 xfree((
void*)insert_str);
1696 if (insert_str != str && insert_str != insert_buf)
1697 xfree((
void*)insert_str);
1746 #if SIZEOF_SIZE_T > SIZEOF_INT
1809 return data.ascii_compat_name;
1815 unsigned const char *sp, *se;
1816 unsigned char *ds, *
dp, *de;
1834 unsigned long new_capa = (
unsigned long)dlen + len + max_output;
1840 sp = (
const unsigned char *)ss;
1846 len -= (
const char *)sp - ss;
1847 ss = (
const char *)sp;
1944 const char *dname = 0;
1948 dname =
"universal_newline";
1951 dname =
"crlf_newline";
1954 dname =
"cr_newline";
1963 for (i=0; i < num_trans; i++) {
1980 int has_description = 0;
1985 if (*sname !=
'\0' || *dname !=
'\0') {
1988 else if (*dname ==
'\0')
1992 has_description = 1;
1999 const char *pre =
"";
2000 if (has_description)
2026 has_description = 1;
2028 if (!has_description) {
2065 else if (readagain_len) {
2066 bytes2 =
rb_str_new(err+error_len, readagain_len);
2102 const char *start, *end;
2126 mesg =
rb_sprintf(
"%s to %s in conversion from %s",
2150 unsigned char *(*resize_destination)(
VALUE,
size_t,
size_t),
2152 unsigned char **out_start_ptr,
2153 unsigned char **out_pos,
2154 unsigned char **out_stop_ptr)
2156 size_t len = (*out_pos - *out_start_ptr);
2157 size_t new_len = (len + max_output) * 2;
2158 *out_start_ptr = resize_destination(destination, len, new_len);
2159 *out_pos = *out_start_ptr + len;
2160 *out_stop_ptr = *out_start_ptr + new_len;
2168 const unsigned char *replacement;
2169 const char *repl_enc;
2170 const char *ins_enc;
2185 replacement = (
unsigned char *)
"?";
2199 const unsigned char *str,
size_t len,
const char *encname)
2201 unsigned char *str2;
2203 const char *encname2;
2209 MEMCPY(str2, str,
unsigned char, len);
2245 #define hash_fallback rb_hash_aref
2267 const unsigned char *in_stop,
unsigned char *out_stop,
2269 unsigned char *(*resize_destination)(
VALUE,
size_t,
size_t),
2270 const char *src_encoding,
2271 const char *dst_encoding,
2278 unsigned char *out_start = *out_pos;
2314 rep = (*fallback_func)(fallback, rep);
2319 if ((
int)ret == -1) {
2335 more_output_buffer(destination, resize_destination, max_output, &out_start, out_pos, &out_stop);
2345 transcode_loop(
const unsigned char **in_pos,
unsigned char **out_pos,
2346 const unsigned char *in_stop,
unsigned char *out_stop,
2348 unsigned char *(*resize_destination)(
VALUE,
size_t,
size_t),
2349 const char *src_encoding,
2350 const char *dst_encoding,
2357 unsigned char *out_start = *out_pos;
2358 const unsigned char *ptr;
2372 unsigned char input_byte;
2373 const unsigned char *p = &input_byte;
2376 if (ptr < in_stop) {
2378 ret =
rb_econv_convert(ec, &p, p+1, out_pos, out_stop, ECONV_PARTIAL_INPUT);
2387 if (&input_byte != p)
2388 ptr += p - &input_byte;
2399 more_output_buffer(destination, resize_destination, max_output, &out_start, out_pos, &out_stop);
2420 static unsigned char *
2473 #ifdef ENABLE_ECONV_NEWLINE_OPTION
2500 int setflags = 0, newlineflag = 0;
2505 newlineflag |= !
NIL_P(v);
2510 newlineflag |= !
NIL_P(v);
2515 newlineflag |= !
NIL_P(v);
2519 ecflags |= setflags;
2532 if (
NIL_P(opthash)) {
2564 if (!
NIL_P(newhash))
2583 if (
NIL_P(opthash)) {
2588 rb_bug(
"rb_econv_open_opts called with invalid opthash");
2592 ec =
rb_econv_open(source_encoding, destination_encoding, ecflags);
2596 if (!
NIL_P(replacement)) {
2642 const char *sname, *dname;
2643 int sencidx, dencidx;
2645 dencidx =
enc_arg(arg1, &dname, &denc);
2653 sencidx =
enc_arg(arg2, &sname, &senc);
2668 volatile VALUE arg1, arg2;
2670 unsigned char *
buf, *
bp, *sp;
2671 const unsigned char *fromp;
2673 const char *sname, *dname;
2675 int explicitly_invalid_replace =
TRUE;
2682 if (!ecflags)
return -1;
2686 explicitly_invalid_replace =
FALSE;
2693 arg2 = argc<=1 ?
Qnil : argv[1];
2700 if (senc && senc == denc) {
2703 if (!
NIL_P(ecopts)) {
2707 if (
NIL_P(dest)) dest = str;
2711 return NIL_P(arg2) ? -1 : dencidx;
2719 return NIL_P(arg2) ? -1 : dencidx;
2736 if (fromp != sp+slen) {
2809 if (encidx < 0)
return str;
2810 if (newstr == str) {
2890 int encidx =
str_transcode0(argc, argv, &newstr, ecflags, ecopts);
2898 if (newstr == str) {
2981 const char *arg_name, *result_name;
2984 enc_arg(&arg, &arg_name, &arg_enc);
2988 if (result_name ==
NULL)
2998 volatile VALUE *snamev_p,
volatile VALUE *dnamev_p,
2999 const char **sname_p,
const char **dname_p,
3004 VALUE opt, flags_v, ecopts;
3006 const char *sname, *dname;
3010 argc =
rb_scan_args(argc, argv,
"21:", snamev_p, dnamev_p, &flags_v, &opt);
3012 if (!
NIL_P(flags_v)) {
3019 else if (!
NIL_P(opt)) {
3052 *ecflags_p = ecflags;
3065 if (num_decorators == -1)
3081 rb_ary_store(convpath, len + num_decorators - 1, pair);
3085 rb_ary_store(convpath, len + num_decorators - 1, pair);
3089 for (i = 0; i < num_decorators; i++)
3101 if (*ary_p ==
Qnil) {
3142 volatile VALUE snamev, dnamev;
3143 const char *sname, *dname;
3149 econv_args(argc, argv, &snamev, &dnamev, &sname, &dname, &senc, &denc, &ecflags, &ecopts);
3154 if (
NIL_P(convpath))
3174 return RTEST(convpath);
3200 const char **sname_p,
const char **dname_p,
3208 const char *sname, *dname;
3214 volatile VALUE snamev, dnamev;
3218 if (RARRAY_LEN(pair) != 2)
3221 enc_arg(&snamev, &sname, &senc);
3223 enc_arg(&dnamev, &dname, &denc);
3241 if (ret == -1 || arg.
ret == -1)
3376 volatile VALUE snamev, dnamev;
3377 const char *sname, *dname;
3393 econv_args(argc, argv, &snamev, &dnamev, &sname, &dname, &senc, &denc, &ecflags, &ecopts);
3434 return rb_sprintf(
"#<%s: uninitialized>", cname);
3684 const unsigned char *ip, *is;
3685 unsigned char *op, *os;
3686 long output_byteoffset, output_bytesize;
3687 unsigned long output_byteend;
3690 argc =
rb_scan_args(argc, argv,
"23:", &input, &output, &output_byteoffset_v, &output_bytesize_v, &flags_v, &opt);
3692 if (
NIL_P(output_byteoffset_v))
3693 output_byteoffset = 0;
3695 output_byteoffset =
NUM2LONG(output_byteoffset_v);
3697 if (
NIL_P(output_bytesize_v))
3698 output_bytesize = 0;
3700 output_bytesize =
NUM2LONG(output_bytesize_v);
3702 if (!
NIL_P(flags_v)) {
3708 else if (!
NIL_P(opt)) {
3727 if (
NIL_P(output_bytesize_v)) {
3735 if (
NIL_P(output_byteoffset_v))
3738 if (output_byteoffset < 0)
3744 if (output_bytesize < 0)
3747 output_byteend = (
unsigned long)output_byteoffset +
3748 (
unsigned long)output_bytesize;
3750 if (output_byteend < (
unsigned long)output_byteoffset ||
3765 op = (
unsigned char *)
RSTRING_PTR(output) + output_byteoffset;
3766 os = op + output_bytesize;
3774 if (
LONG_MAX / 2 < output_bytesize)
3776 output_bytesize *= 2;
3777 output_byteoffset_v =
Qnil;
3855 rb_bug(
"unexpected result of econv_primitive_convert");
3899 rb_bug(
"unexpected result of econv_primitive_convert");
4041 const char *insert_enc;
4098 if (putbackable < n)
4421 #ifdef ENABLE_ECONV_NEWLINE_OPTION