1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

* transcode.c (get_replacement_character): temporary function,

get characters for replacement mode.

* transcode.c (transcode_loop): add undef key and replace value.

* transcode.c (str_transcode): ditto.

* transcode.c (Init_transcode): define sym_undef and sym_replace.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@18062 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
naruse 2008-07-14 06:27:26 +00:00
parent 641d6ece1e
commit ef62472e44
2 changed files with 91 additions and 5 deletions

View file

@ -1,3 +1,14 @@
Mon Jul 14 15:18:30 2008 NARUSE, Yui <naruse@ruby-lang.org>
* transcode.c (get_replacement_character): temporary function,
get characters for replacement mode.
* transcode.c (transcode_loop): add undef key and replace value.
* transcode.c (str_transcode): ditto.
* transcode.c (Init_transcode): define sym_undef and sym_replace.
Mon Jul 14 15:16:40 2008 Kazuhiro NISHIYAMA <zn@mbf.nifty.com>
* test/ruby/test_variable.rb (TestVariable#test_global_variable_0):

View file

@ -15,8 +15,11 @@
#include "transcode_data.h"
#include <ctype.h>
static VALUE sym_invalid, sym_ignore;
static VALUE sym_invalid, sym_undef, sym_ignore, sym_replace;
#define INVALID_IGNORE 0x1
#define INVALID_REPLACE 0x2
#define UNDEF_IGNORE 0x10
#define UNDEF_REPLACE 0x20
/*
* Dispatch data and logic
@ -119,6 +122,36 @@ transcode_dispatch(const char* from_encoding, const char* to_encoding)
return (rb_transcoder *)val;
}
static const char*
get_replacement_character(rb_encoding *enc)
{
static rb_encoding *utf16be_encoding, *utf16le_encoding;
static rb_encoding *utf32be_encoding, *utf32le_encoding;
if (!utf16be_encoding) {
utf16be_encoding = rb_enc_find("UTF-16BE");
utf16le_encoding = rb_enc_find("UTF-16LE");
utf32be_encoding = rb_enc_find("UTF-32BE");
utf32le_encoding = rb_enc_find("UTF-32LE");
}
if (rb_enc_asciicompat(enc)) {
return "?";
}
else if (utf16be_encoding = enc) {
return "\x00?";
}
else if (utf16le_encoding = enc) {
return "?\x00";
}
else if (utf32be_encoding = enc) {
return "\x00\x00\x00?";
}
else if (utf32le_encoding = enc) {
return "?\x00\x00\x00";
}
else {
return "?";
}
}
/*
* Transcoding engine logic
@ -139,6 +172,7 @@ transcode_loop(unsigned char **in_pos, unsigned char **out_pos,
unsigned char next_byte;
int from_utf8 = my_transcoder->from_utf8;
unsigned char *out_s = out_stop - my_transcoder->max_output + 1;
rb_encoding *to_encoding = rb_enc_find(my_transcoder->to_encoding);
while (in_p < in_stop) {
char_start = in_p;
next_table = conv_tree_start;
@ -209,9 +243,7 @@ transcode_loop(unsigned char **in_pos, unsigned char **out_pos,
case INVALID:
goto invalid;
case UNDEF:
/* todo: add code for alternate behaviors */
rb_raise(rb_eRuntimeError /*@@@change exception*/, "conversion undefined for byte sequence (maybe invalid byte sequence)");
continue;
goto undef;
}
continue;
invalid:
@ -220,8 +252,31 @@ transcode_loop(unsigned char **in_pos, unsigned char **out_pos,
if (opt&INVALID_IGNORE) {
continue;
}
else if (opt&INVALID_REPLACE) {
const char *rep = get_replacement_character(to_encoding);
do {
*out_p++ = *rep++;
} while (*rep);
continue;
}
rb_raise(rb_eRuntimeError /*change exception*/, "invalid byte sequence");
continue;
undef:
/* valid character in from encoding
* but no related character(s) in to encoding */
/* todo: add more alternative behaviors */
if (opt&UNDEF_IGNORE) {
continue;
}
else if (opt&UNDEF_REPLACE) {
const char *rep = get_replacement_character(to_encoding);
do {
*out_p++ = *rep++;
} while (*rep);
continue;
}
rb_raise(rb_eRuntimeError /*@@@change exception*/, "conversion undefined for byte sequence (maybe invalid byte sequence)");
continue;
}
/* cleanup */
*in_pos = in_p;
@ -265,11 +320,29 @@ str_transcode(int argc, VALUE *argv, VALUE *self)
argc--;
v = rb_hash_aref(opt, sym_invalid);
if (NIL_P(v)) {
rb_raise(rb_eArgError, "unknown value for invalid: setting");
}
else if (v==sym_ignore) {
options |= INVALID_IGNORE;
}
else if (v==sym_replace) {
options |= INVALID_REPLACE;
v = rb_hash_aref(opt, sym_replace);
}
else {
rb_raise(rb_eArgError, "unknown value for invalid: setting");
}
v = rb_hash_aref(opt, sym_undef);
if (NIL_P(v)) {
}
else if (v==sym_ignore) {
options |= UNDEF_IGNORE;
}
else if (v==sym_replace) {
options |= UNDEF_REPLACE;
}
else {
rb_raise(rb_eArgError, "unknown value for undef: setting");
}
}
if (argc < 1 || argc > 2) {
rb_raise(rb_eArgError, "wrong number of arguments (%d for 1..2)", argc);
@ -451,7 +524,9 @@ Init_transcode(void)
transcoder_lib_table = st_init_strcasetable();
sym_invalid = ID2SYM(rb_intern("invalid"));
sym_undef = ID2SYM(rb_intern("undef"));
sym_ignore = ID2SYM(rb_intern("ignore"));
sym_replace = ID2SYM(rb_intern("replace"));
rb_define_method(rb_cString, "encode", str_encode, -1);
rb_define_method(rb_cString, "encode!", str_encode_bang, -1);