class Encoding::Converter
Encoding Konvertierungsklasse.
Constants
- AFTER_OUTPUT
-
Stoppt die Konvertierung, nachdem eine Ausgabe abgeschlossen ist, aber bevor die gesamte Eingabe verarbeitet wurde. Siehe
primitive_convertfür ein Beispiel. - CRLF_NEWLINE_DECORATOR
-
Dekorator zur Konvertierung von LF in CRLF
- CR_NEWLINE_DECORATOR
-
Dekorator zur Konvertierung von LF in CR
- INVALID_MASK
-
Maske für ungültige Byte-Sequenzen
- INVALID_REPLACE
-
Ungültige Byte-Sequenzen ersetzen
- LF_NEWLINE_DECORATOR
-
Dekorator zur Konvertierung von CRLF und CR zu LF beim Schreiben
- PARTIAL_INPUT
-
Gibt an, dass die Quelle Teil einer größeren Zeichenkette sein kann. Siehe
primitive_convertfür ein Beispiel. - UNDEF_HEX_CHARREF
-
Ersetzt Byte-Sequenzen, die in der Zielkodierung undefiniert sind, durch eine XML-hexadezimale Zeichenreferenz. Dies ist für XML-Konvertierungen gültig.
- UNDEF_MASK
-
Maske für ein gültiges Zeichen in der Quellkodierung, aber kein zugehöriges Zeichen in der Zielkodierung.
- UNDEF_REPLACE
-
Ersetzt Byte-Sequenzen, die in der Zielkodierung undefiniert sind.
- UNIVERSAL_NEWLINE_DECORATOR
-
Dekorator zur Konvertierung von CRLF und CR zu LF
- XML_ATTR_CONTENT_DECORATOR
-
Als XML AttValue escapen
- XML_ATTR_QUOTE_DECORATOR
-
Als XML AttValue escapen
- XML_TEXT_DECORATOR
-
Als XML CharData escapen
Öffentliche Klassenmethoden
Source
static VALUE
econv_s_asciicompat_encoding(VALUE klass, VALUE arg)
{
const char *arg_name, *result_name;
rb_encoding *arg_enc, *result_enc;
VALUE enc = Qnil;
enc_arg(&arg, &arg_name, &arg_enc);
result_name = rb_econv_asciicompat_encoding(arg_name);
if (result_name) {
result_enc = make_encoding(result_name);
enc = rb_enc_from_encoding(result_enc);
}
return enc;
}
Gibt die entsprechende ASCII-kompatible Kodierung zurück.
Gibt nil zurück, wenn das Argument eine ASCII-kompatible Kodierung ist.
“corresponding ASCII compatible encoding” ist eine ASCII-kompatible Kodierung, die exakt die gleichen Zeichen wie die gegebene ASCII-inkompatible Kodierung darstellen kann. Daher tritt kein Fehler bei undefinierter Konvertierung auf, wenn zwischen den beiden Kodierungen konvertiert wird.
Encoding::Converter.asciicompat_encoding("ISO-2022-JP") #=> #<Encoding:stateless-ISO-2022-JP> Encoding::Converter.asciicompat_encoding("UTF-16BE") #=> #<Encoding:UTF-8> Encoding::Converter.asciicompat_encoding("UTF-8") #=> nil
Source
static VALUE
econv_init(int argc, VALUE *argv, VALUE self)
{
VALUE ecopts;
VALUE snamev, dnamev;
const char *sname, *dname;
rb_encoding *senc, *denc;
rb_econv_t *ec;
int ecflags;
VALUE convpath;
if (rb_check_typeddata(self, &econv_data_type)) {
rb_raise(rb_eTypeError, "already initialized");
}
if (argc == 1 && !NIL_P(convpath = rb_check_array_type(argv[0]))) {
ec = rb_econv_init_by_convpath(self, convpath, &sname, &dname, &senc, &denc);
ecflags = 0;
ecopts = Qnil;
}
else {
econv_args(argc, argv, &snamev, &dnamev, &sname, &dname, &senc, &denc, &ecflags, &ecopts);
ec = rb_econv_open_opts(sname, dname, ecflags, ecopts);
}
if (!ec) {
VALUE exc = rb_econv_open_exc(sname, dname, ecflags);
RB_GC_GUARD(snamev);
RB_GC_GUARD(dnamev);
rb_exc_raise(exc);
}
if (!DECORATOR_P(sname, dname)) {
if (!senc)
senc = make_dummy_encoding(sname);
if (!denc)
denc = make_dummy_encoding(dname);
RB_GC_GUARD(snamev);
RB_GC_GUARD(dnamev);
}
ec->source_encoding = senc;
ec->destination_encoding = denc;
DATA_PTR(self) = ec;
return self;
}
mögliche Options-Elemente
hash form:
:invalid => nil # raise error on invalid byte sequence (default)
:invalid => :replace # replace invalid byte sequence
:undef => nil # raise error on undefined conversion (default)
:undef => :replace # replace undefined conversion
:replace => string # replacement string ("?" or "\uFFFD" if not specified)
:newline => :universal # decorator for converting CRLF and CR to LF
:newline => :lf # decorator for converting CRLF and CR to LF when writing
:newline => :crlf # decorator for converting LF to CRLF
:newline => :cr # decorator for converting LF to CR
:universal_newline => true # decorator for converting CRLF and CR to LF
:crlf_newline => true # decorator for converting LF to CRLF
:cr_newline => true # decorator for converting LF to CR
:lf_newline => true # decorator for converting CRLF and CR to LF when writing
:xml => :text # escape as XML CharData.
:xml => :attr # escape as XML AttValue
integer form:
Encoding::Converter::INVALID_REPLACE
Encoding::Converter::UNDEF_REPLACE
Encoding::Converter::UNDEF_HEX_CHARREF
Encoding::Converter::UNIVERSAL_NEWLINE_DECORATOR
Encoding::Converter::LF_NEWLINE_DECORATOR
Encoding::Converter::CRLF_NEWLINE_DECORATOR
Encoding::Converter::CR_NEWLINE_DECORATOR
Encoding::Converter::XML_TEXT_DECORATOR
Encoding::Converter::XML_ATTR_CONTENT_DECORATOR
Encoding::Converter::XML_ATTR_QUOTE_DECORATOR
Encoding::Converter.new erstellt eine Instanz von Encoding::Converter.
Source_encoding und destination_encoding sollten eine Zeichenkette oder ein Encoding-Objekt sein.
opt sollte nil, ein Hash oder eine Ganzzahl sein.
convpath sollte ein Array sein. convpath kann enthalten
-
Zwei-Element-Arrays, die Kodierungen oder Kodierungsnamen enthalten, oder
-
Zeichenketten, die Dekoratornamen darstellen.
Encoding::Converter.new nimmt optional eine Option entgegen. Die Option sollte ein Hash oder eine Ganzzahl sein. Der Options-Hash kann :invalid => nil, etc. enthalten. Die Options-Ganzzahl sollte eine logische ODER-Verknüpfung von Konstanten wie Encoding::Converter::INVALID_REPLACE, etc. sein.
- :invalid => nil
-
Fehler bei ungültiger Byte-Sequenz auslösen. Dies ist das Standardverhalten.
- :invalid => :replace
-
Ungültige Byte-Sequenz durch Ersatzzeichenkette ersetzen.
- :undef => nil
-
Fehler auslösen, wenn ein Zeichen in
source_encodingnicht in destination_encoding definiert ist. Dies ist das Standardverhalten. - :undef => :replace
-
Undefiniertes Zeichen in
destination_encodingdurch Ersatzzeichenkette ersetzen. - :replace => string
-
Gibt die Ersatzzeichenkette an. Wenn nicht angegeben, wird “uFFFD” für Unicode-Kodierungen und “?” für andere verwendet.
- :universal_newline => true
-
CRLF und CR in LF konvertieren.
- :crlf_newline => true
-
LF in CRLF konvertieren.
- :cr_newline => true
-
LF in CR konvertieren.
- :lf_newline => true
-
CRLF und CR in LF konvertieren (beim Schreiben).
- :xml => :text
-
Als XML CharData escapen. Diese Form kann als HTML 4.0 PCDATA verwendet werden.
-
‘&’ -> ‘&’
-
‘<’ -> ‘<’
-
‘>’ -> ‘>’
-
undefinierte Zeichen in
destination_encoding-> hexadezimale CharRef wie &#xHH;
-
- :xml => :attr
-
Als XML AttValue escapen. Das konvertierte Ergebnis wird als „…” zitiert. Diese Form kann als HTML 4.0 Attributwert verwendet werden.
-
‘&’ -> ‘&’
-
‘<’ -> ‘<’
-
‘>’ -> ‘>’
-
‘“’ -> ‘"’
-
undefinierte Zeichen in
destination_encoding-> hexadezimale CharRef wie &#xHH;
-
Beispiele
# UTF-16BE to UTF-8 ec = Encoding::Converter.new("UTF-16BE", "UTF-8") # Usually, decorators such as newline conversion are inserted last. ec = Encoding::Converter.new("UTF-16BE", "UTF-8", :universal_newline => true) p ec.convpath #=> [[#<Encoding:UTF-16BE>, #<Encoding:UTF-8>], # "universal_newline"] # But, if the last encoding is ASCII incompatible, # decorators are inserted before the last conversion. ec = Encoding::Converter.new("UTF-8", "UTF-16BE", :crlf_newline => true) p ec.convpath #=> ["crlf_newline", # [#<Encoding:UTF-8>, #<Encoding:UTF-16BE>]] # Conversion path can be specified directly. ec = Encoding::Converter.new(["universal_newline", ["EUC-JP", "UTF-8"], ["UTF-8", "UTF-16BE"]]) p ec.convpath #=> ["universal_newline", # [#<Encoding:EUC-JP>, #<Encoding:UTF-8>], # [#<Encoding:UTF-8>, #<Encoding:UTF-16BE>]]
Source
static VALUE
econv_s_search_convpath(int argc, VALUE *argv, VALUE klass)
{
VALUE snamev, dnamev;
const char *sname, *dname;
rb_encoding *senc, *denc;
int ecflags;
VALUE ecopts;
VALUE convpath;
econv_args(argc, argv, &snamev, &dnamev, &sname, &dname, &senc, &denc, &ecflags, &ecopts);
convpath = Qnil;
transcode_search_path(sname, dname, search_convpath_i, &convpath);
if (NIL_P(convpath)) {
VALUE exc = rb_econv_open_exc(sname, dname, ecflags);
RB_GC_GUARD(snamev);
RB_GC_GUARD(dnamev);
rb_exc_raise(exc);
}
if (decorate_convpath(convpath, ecflags) == -1) {
VALUE exc = rb_econv_open_exc(sname, dname, ecflags);
RB_GC_GUARD(snamev);
RB_GC_GUARD(dnamev);
rb_exc_raise(exc);
}
return convpath;
}
Gibt einen Konvertierungspfad zurück.
p Encoding::Converter.search_convpath("ISO-8859-1", "EUC-JP") #=> [[#<Encoding:ISO-8859-1>, #<Encoding:UTF-8>], # [#<Encoding:UTF-8>, #<Encoding:EUC-JP>]] p Encoding::Converter.search_convpath("ISO-8859-1", "EUC-JP", universal_newline: true) or p Encoding::Converter.search_convpath("ISO-8859-1", "EUC-JP", newline: :universal) #=> [[#<Encoding:ISO-8859-1>, #<Encoding:UTF-8>], # [#<Encoding:UTF-8>, #<Encoding:EUC-JP>], # "universal_newline"] p Encoding::Converter.search_convpath("ISO-8859-1", "UTF-32BE", universal_newline: true) or p Encoding::Converter.search_convpath("ISO-8859-1", "UTF-32BE", newline: :universal) #=> [[#<Encoding:ISO-8859-1>, #<Encoding:UTF-8>], # "universal_newline", # [#<Encoding:UTF-8>, #<Encoding:UTF-32BE>]]
Öffentliche Instanzmethoden
Source
static VALUE
econv_equal(VALUE self, VALUE other)
{
rb_econv_t *ec1 = check_econv(self);
rb_econv_t *ec2;
int i;
if (!rb_typeddata_is_kind_of(other, &econv_data_type)) {
return Qnil;
}
ec2 = DATA_PTR(other);
if (!ec2) return Qfalse;
if (ec1->source_encoding_name != ec2->source_encoding_name &&
strcmp(ec1->source_encoding_name, ec2->source_encoding_name))
return Qfalse;
if (ec1->destination_encoding_name != ec2->destination_encoding_name &&
strcmp(ec1->destination_encoding_name, ec2->destination_encoding_name))
return Qfalse;
if (ec1->flags != ec2->flags) return Qfalse;
if (ec1->replacement_enc != ec2->replacement_enc &&
strcmp(ec1->replacement_enc, ec2->replacement_enc))
return Qfalse;
if (ec1->replacement_len != ec2->replacement_len) return Qfalse;
if (ec1->replacement_str != ec2->replacement_str &&
memcmp(ec1->replacement_str, ec2->replacement_str, ec2->replacement_len))
return Qfalse;
if (ec1->num_trans != ec2->num_trans) return Qfalse;
for (i = 0; i < ec1->num_trans; i++) {
if (ec1->elems[i].tc->transcoder != ec2->elems[i].tc->transcoder)
return Qfalse;
}
return Qtrue;
}
Source
static VALUE
econv_convert(VALUE self, VALUE source_string)
{
VALUE ret, dst;
VALUE av[5];
int ac;
rb_econv_t *ec = check_econv(self);
StringValue(source_string);
dst = rb_str_new(NULL, 0);
av[0] = rb_str_dup(source_string);
av[1] = dst;
av[2] = Qnil;
av[3] = Qnil;
av[4] = INT2NUM(ECONV_PARTIAL_INPUT);
ac = 5;
ret = econv_primitive_convert(ac, av, self);
if (ret == sym_invalid_byte_sequence ||
ret == sym_undefined_conversion ||
ret == sym_incomplete_input) {
VALUE exc = make_econv_exception(ec);
rb_exc_raise(exc);
}
if (ret == sym_finished) {
rb_raise(rb_eArgError, "converter already finished");
}
if (ret != sym_source_buffer_empty) {
rb_bug("unexpected result of econv_primitive_convert");
}
return dst;
}
Konvertiert source_string und gibt destination_string zurück.
source_string wird als Teil von source angenommen. d.h. :partial_input=>true wird intern angegeben. finish Methode sollte zuletzt verwendet werden.
ec = Encoding::Converter.new("utf-8", "euc-jp") puts ec.convert("\u3042").dump #=> "\xA4\xA2" puts ec.finish.dump #=> "" ec = Encoding::Converter.new("euc-jp", "utf-8") puts ec.convert("\xA4").dump #=> "" puts ec.convert("\xA2").dump #=> "\xE3\x81\x82" puts ec.finish.dump #=> "" ec = Encoding::Converter.new("utf-8", "iso-2022-jp") puts ec.convert("\xE3").dump #=> "".force_encoding("ISO-2022-JP") puts ec.convert("\x81").dump #=> "".force_encoding("ISO-2022-JP") puts ec.convert("\x82").dump #=> "\e$B$\"".force_encoding("ISO-2022-JP") puts ec.finish.dump #=> "\e(B".force_encoding("ISO-2022-JP")
Wenn ein Konvertierungsfehler auftritt, wird Encoding::UndefinedConversionError oder Encoding::InvalidByteSequenceError ausgelöst. Encoding::Converter#convert liefert keine Methoden zur Wiederherstellung oder zum Neustart von diesen Ausnahmen. Wenn Sie diese Konvertierungsfehler behandeln möchten, verwenden Sie Encoding::Converter#primitive_convert.
Source
static VALUE
econv_convpath(VALUE self)
{
rb_econv_t *ec = check_econv(self);
VALUE result;
int i;
result = rb_ary_new();
for (i = 0; i < ec->num_trans; i++) {
const rb_transcoder *tr = ec->elems[i].tc->transcoder;
VALUE v;
if (DECORATOR_P(tr->src_encoding, tr->dst_encoding))
v = rb_str_new_cstr(tr->dst_encoding);
else
v = rb_assoc_new(make_encobj(tr->src_encoding), make_encobj(tr->dst_encoding));
rb_ary_push(result, v);
}
return result;
}
Gibt den Konvertierungspfad von ec zurück.
Das Ergebnis ist ein Array von Konvertierungen.
ec = Encoding::Converter.new("ISO-8859-1", "EUC-JP", crlf_newline: true) p ec.convpath #=> [[#<Encoding:ISO-8859-1>, #<Encoding:UTF-8>], # [#<Encoding:UTF-8>, #<Encoding:EUC-JP>], # "crlf_newline"]
Jedes Element des Arrays ist ein Paar von Kodierungen oder eine Zeichenkette. Ein Paar bedeutet eine Kodierungskonvertierung. Eine Zeichenkette bedeutet einen Dekorator.
Im obigen Beispiel, [#<Encoding:ISO-8859-1>,
Source
static VALUE
econv_destination_encoding(VALUE self)
{
rb_econv_t *ec = check_econv(self);
return econv_get_encoding(ec->destination_encoding);
}
Gibt die Zielkodierung als Encoding-Objekt zurück.
Source
static VALUE
econv_finish(VALUE self)
{
VALUE ret, dst;
VALUE av[5];
int ac;
rb_econv_t *ec = check_econv(self);
dst = rb_str_new(NULL, 0);
av[0] = Qnil;
av[1] = dst;
av[2] = Qnil;
av[3] = Qnil;
av[4] = INT2FIX(0);
ac = 5;
ret = econv_primitive_convert(ac, av, self);
if (ret == sym_invalid_byte_sequence ||
ret == sym_undefined_conversion ||
ret == sym_incomplete_input) {
VALUE exc = make_econv_exception(ec);
rb_exc_raise(exc);
}
if (ret != sym_finished) {
rb_bug("unexpected result of econv_primitive_convert");
}
return dst;
}
Beendet den Konverter. Er gibt den letzten Teil der konvertierten Zeichenkette zurück.
ec = Encoding::Converter.new("utf-8", "iso-2022-jp") p ec.convert("\u3042") #=> "\e$B$\"" p ec.finish #=> "\e(B"
Source
static VALUE
econv_insert_output(VALUE self, VALUE string)
{
const char *insert_enc;
int ret;
rb_econv_t *ec = check_econv(self);
StringValue(string);
insert_enc = rb_econv_encoding_to_insert_output(ec);
string = rb_str_encode(string, rb_enc_from_encoding(rb_enc_find(insert_enc)), 0, Qnil);
ret = rb_econv_insert_output(ec, (const unsigned char *)RSTRING_PTR(string), RSTRING_LEN(string), insert_enc);
if (ret == -1) {
rb_raise(rb_eArgError, "too big string");
}
return Qnil;
}
Fügt string in den Kodierungskonverter ein. Die Zeichenkette wird in die Zielkodierung konvertiert und bei späteren Konvertierungen ausgegeben.
Wenn die Zielkodierung zustandsbehaftet ist, wird string entsprechend dem Zustand konvertiert und der Zustand wird aktualisiert.
Diese Methode sollte nur verwendet werden, wenn ein Konvertierungsfehler auftritt.
ec = Encoding::Converter.new("utf-8", "iso-8859-1") src = "HIRAGANA LETTER A is \u{3042}." dst = "" p ec.primitive_convert(src, dst) #=> :undefined_conversion puts "[#{dst.dump}, #{src.dump}]" #=> ["HIRAGANA LETTER A is ", "."] ec.insert_output("<err>") p ec.primitive_convert(src, dst) #=> :finished puts "[#{dst.dump}, #{src.dump}]" #=> ["HIRAGANA LETTER A is <err>.", ""] ec = Encoding::Converter.new("utf-8", "iso-2022-jp") src = "\u{306F 3041 3068 2661 3002}" # U+2661 is not representable in iso-2022-jp dst = "" p ec.primitive_convert(src, dst) #=> :undefined_conversion puts "[#{dst.dump}, #{src.dump}]" #=> ["\e$B$O$!$H".force_encoding("ISO-2022-JP"), "\xE3\x80\x82"] ec.insert_output "?" # state change required to output "?". p ec.primitive_convert(src, dst) #=> :finished puts "[#{dst.dump}, #{src.dump}]" #=> ["\e$B$O$!$H\e(B?\e$B!#\e(B".force_encoding("ISO-2022-JP"), ""]
Source
static VALUE
econv_inspect(VALUE self)
{
const char *cname = rb_obj_classname(self);
rb_econv_t *ec;
TypedData_Get_Struct(self, rb_econv_t, &econv_data_type, ec);
if (!ec)
return rb_sprintf("#<%s: uninitialized>", cname);
else {
const char *sname = ec->source_encoding_name;
const char *dname = ec->destination_encoding_name;
VALUE str;
str = rb_sprintf("#<%s: ", cname);
econv_description(sname, dname, ec->flags, str);
rb_str_cat2(str, ">");
return str;
}
}
Gibt eine druckbare Version von ec zurück
ec = Encoding::Converter.new("iso-8859-1", "utf-8") puts ec.inspect #=> #<Encoding::Converter: ISO-8859-1 to UTF-8>
Source
static VALUE
econv_last_error(VALUE self)
{
rb_econv_t *ec = check_econv(self);
VALUE exc;
exc = make_econv_exception(ec);
if (NIL_P(exc))
return Qnil;
return exc;
}
Gibt ein Ausnameobjekt für die letzte Konvertierung zurück. Gibt nil zurück, wenn die letzte Konvertierung keinen Fehler erzeugt hat.
“Fehler” bedeutet, dass Encoding::InvalidByteSequenceError und Encoding::UndefinedConversionError für Encoding::Converter#convert und :invalid_byte_sequence, :incomplete_input und :undefined_conversion für Encoding::Converter#primitive_convert.
ec = Encoding::Converter.new("utf-8", "iso-8859-1") p ec.primitive_convert(src="\xf1abcd", dst="") #=> :invalid_byte_sequence p ec.last_error #=> #<Encoding::InvalidByteSequenceError: "\xF1" followed by "a" on UTF-8> p ec.primitive_convert(src, dst, nil, 1) #=> :destination_buffer_full p ec.last_error #=> nil
Source
static VALUE
econv_primitive_convert(int argc, VALUE *argv, VALUE self)
{
VALUE input, output, output_byteoffset_v, output_bytesize_v, opt, flags_v;
rb_econv_t *ec = check_econv(self);
rb_econv_result_t res;
const unsigned char *ip, *is;
unsigned char *op, *os;
long output_byteoffset, output_bytesize;
unsigned long output_byteend;
int flags;
argc = rb_scan_args(argc, argv, "23:", &input, &output, &output_byteoffset_v, &output_bytesize_v, &flags_v, &opt);
if (NIL_P(output_byteoffset_v))
output_byteoffset = 0; /* dummy */
else
output_byteoffset = NUM2LONG(output_byteoffset_v);
if (NIL_P(output_bytesize_v))
output_bytesize = 0; /* dummy */
else
output_bytesize = NUM2LONG(output_bytesize_v);
if (!NIL_P(flags_v)) {
if (!NIL_P(opt)) {
rb_error_arity(argc + 1, 2, 5);
}
flags = NUM2INT(rb_to_int(flags_v));
}
else if (!NIL_P(opt)) {
VALUE v;
flags = 0;
v = rb_hash_aref(opt, sym_partial_input);
if (RTEST(v))
flags |= ECONV_PARTIAL_INPUT;
v = rb_hash_aref(opt, sym_after_output);
if (RTEST(v))
flags |= ECONV_AFTER_OUTPUT;
}
else {
flags = 0;
}
StringValue(output);
if (!NIL_P(input))
StringValue(input);
rb_str_modify(output);
if (NIL_P(output_bytesize_v)) {
output_bytesize = rb_str_capacity(output);
if (!NIL_P(input) && output_bytesize < RSTRING_LEN(input))
output_bytesize = RSTRING_LEN(input);
}
retry:
if (NIL_P(output_byteoffset_v))
output_byteoffset = RSTRING_LEN(output);
if (output_byteoffset < 0)
rb_raise(rb_eArgError, "negative output_byteoffset");
if (RSTRING_LEN(output) < output_byteoffset)
rb_raise(rb_eArgError, "output_byteoffset too big");
if (output_bytesize < 0)
rb_raise(rb_eArgError, "negative output_bytesize");
output_byteend = (unsigned long)output_byteoffset +
(unsigned long)output_bytesize;
if (output_byteend < (unsigned long)output_byteoffset ||
LONG_MAX < output_byteend)
rb_raise(rb_eArgError, "output_byteoffset+output_bytesize too big");
if (rb_str_capacity(output) < output_byteend)
rb_str_resize(output, output_byteend);
if (NIL_P(input)) {
ip = is = NULL;
}
else {
ip = (const unsigned char *)RSTRING_PTR(input);
is = ip + RSTRING_LEN(input);
}
op = (unsigned char *)RSTRING_PTR(output) + output_byteoffset;
os = op + output_bytesize;
res = rb_econv_convert(ec, &ip, is, &op, os, flags);
rb_str_set_len(output, op-(unsigned char *)RSTRING_PTR(output));
if (!NIL_P(input)) {
rb_str_drop_bytes(input, ip - (unsigned char *)RSTRING_PTR(input));
}
if (NIL_P(output_bytesize_v) && res == econv_destination_buffer_full) {
if (LONG_MAX / 2 < output_bytesize)
rb_raise(rb_eArgError, "too long conversion result");
output_bytesize *= 2;
output_byteoffset_v = Qnil;
goto retry;
}
if (ec->destination_encoding) {
rb_enc_associate(output, ec->destination_encoding);
}
return econv_result_to_symbol(res);
}
mögliche opt-Elemente
hash form: :partial_input => true # source buffer may be part of larger source :after_output => true # stop conversion after output before input integer form: Encoding::Converter::PARTIAL_INPUT Encoding::Converter::AFTER_OUTPUT
mögliche Ergebnisse
:invalid_byte_sequence :incomplete_input :undefined_conversion :after_output :destination_buffer_full :source_buffer_empty :finished
primitive_convert konvertiert source_buffer in destination_buffer.
source_buffer sollte eine Zeichenkette oder nil sein. nil bedeutet eine leere Zeichenkette.
destination_buffer sollte eine Zeichenkette sein.
destination_byteoffset sollte eine Ganzzahl oder nil sein. nil bedeutet das Ende von destination_buffer. Wenn es weggelassen wird, wird nil angenommen.
destination_bytesize sollte eine Ganzzahl oder nil sein. nil bedeutet unbegrenzt. Wenn es weggelassen wird, wird nil angenommen.
opt sollte nil, ein Hash oder eine Ganzzahl sein. nil bedeutet keine Flags. Wenn es weggelassen wird, wird nil angenommen.
primitive_convert konvertiert den Inhalt von source_buffer von Anfang an und speichert das Ergebnis in destination_buffer.
destination_byteoffset und destination_bytesize geben den Bereich an, in den das konvertierte Ergebnis gespeichert wird. destination_byteoffset gibt die Startposition in destination_buffer in Bytes an. Wenn destination_byteoffset nil ist, wird destination_buffer.bytesize verwendet, um das Ergebnis anzuhängen. destination_bytesize gibt die maximale Anzahl von Bytes an. Wenn destination_bytesize nil ist, ist die Zielgröße unbegrenzt. Nach der Konvertierung wird destination_buffer auf destination_byteoffset + tatsächlich erzeugte Anzahl von Bytes vergrößert. Außerdem wird die Kodierung von destination_buffer auf destination_encoding gesetzt.
primitive_convert verwirft den konvertierten Teil von source_buffer. Der verworfene Teil wird in destination_buffer konvertiert oder im Encoding::Converter-Objekt gepuffert.
primitive_convert stoppt die Konvertierung, wenn eine der folgenden Bedingungen erfüllt ist.
-
ungültige Byte-Sequenz im Quellpuffer gefunden (:invalid_byte_sequence)
primitive_errinfoundlast_errorMethoden geben die Details des Fehlers zurück. -
unerwartetes Ende des Quellpuffers (:incomplete_input) Dies tritt nur auf, wenn :partial_input nicht angegeben ist.
primitive_errinfoundlast_errorMethoden geben die Details des Fehlers zurück. -
Zeichen nicht darstellbar in Zielkodierung (:undefined_conversion)
primitive_errinfoundlast_errorMethoden geben die Details des Fehlers zurück. -
nachdem einige Ausgabe erzeugt wurde, bevor die Eingabe abgeschlossen ist (:after_output) Dies tritt nur auf, wenn :after_output angegeben ist.
-
Zielpuffer ist voll (:destination_buffer_full) Dies tritt nur auf, wenn destination_bytesize nicht nil ist.
-
Quellpuffer ist leer (:source_buffer_empty) Dies tritt nur auf, wenn :partial_input angegeben ist.
-
Konvertierung abgeschlossen (:finished)
Beispiel
ec = Encoding::Converter.new("UTF-8", "UTF-16BE") ret = ec.primitive_convert(src="pi", dst="", nil, 100) p [ret, src, dst] #=> [:finished, "", "\x00p\x00i"] ec = Encoding::Converter.new("UTF-8", "UTF-16BE") ret = ec.primitive_convert(src="pi", dst="", nil, 1) p [ret, src, dst] #=> [:destination_buffer_full, "i", "\x00"] ret = ec.primitive_convert(src, dst="", nil, 1) p [ret, src, dst] #=> [:destination_buffer_full, "", "p"] ret = ec.primitive_convert(src, dst="", nil, 1) p [ret, src, dst] #=> [:destination_buffer_full, "", "\x00"] ret = ec.primitive_convert(src, dst="", nil, 1) p [ret, src, dst] #=> [:finished, "", "i"]
Source
static VALUE
econv_primitive_errinfo(VALUE self)
{
rb_econv_t *ec = check_econv(self);
VALUE ary;
ary = rb_ary_new2(5);
rb_ary_store(ary, 0, econv_result_to_symbol(ec->last_error.result));
rb_ary_store(ary, 4, Qnil);
if (ec->last_error.source_encoding)
rb_ary_store(ary, 1, rb_str_new2(ec->last_error.source_encoding));
if (ec->last_error.destination_encoding)
rb_ary_store(ary, 2, rb_str_new2(ec->last_error.destination_encoding));
if (ec->last_error.error_bytes_start) {
rb_ary_store(ary, 3, rb_str_new((const char *)ec->last_error.error_bytes_start, ec->last_error.error_bytes_len));
rb_ary_store(ary, 4, rb_str_new((const char *)ec->last_error.error_bytes_start + ec->last_error.error_bytes_len, ec->last_error.readagain_len));
}
return ary;
}
primitive_errinfo gibt wichtige Informationen bezüglich des letzten Fehlers als ein 5-Element-Array zurück
[result, enc1, enc2, error_bytes, readagain_bytes]
result ist das letzte Ergebnis von primitive_convert.
Andere Elemente sind nur dann aussagekräftig, wenn result :invalid_byte_sequence, :incomplete_input oder :undefined_conversion ist.
enc1 und enc2 geben einen Konvertierungsschritt als Paar von Zeichenketten an. Zum Beispiel konvertiert ein Konverter von EUC-JP zu ISO-8859-1 eine Zeichenkette wie folgt: EUC-JP -> UTF-8 -> ISO-8859-1. Also ist [enc1, enc2] entweder [“EUC-JP”, “UTF-8”] oder [“UTF-8”, “ISO-8859-1”].
error_bytes und readagain_bytes geben die Byte-Sequenzen an, die den Fehler verursacht haben. error_bytes ist der verworfene Teil. readagain_bytes ist der gepufferte Teil, der bei der nächsten Konvertierung erneut gelesen wird.
Beispiel
# \xff is invalid as EUC-JP. ec = Encoding::Converter.new("EUC-JP", "Shift_JIS") ec.primitive_convert(src="\xff", dst="", nil, 10) p ec.primitive_errinfo #=> [:invalid_byte_sequence, "EUC-JP", "Shift_JIS", "\xFF", ""] # HIRAGANA LETTER A (\xa4\xa2 in EUC-JP) is not representable in ISO-8859-1. # Since this error is occur in UTF-8 to ISO-8859-1 conversion, # error_bytes is HIRAGANA LETTER A in UTF-8 (\xE3\x81\x82). ec = Encoding::Converter.new("EUC-JP", "ISO-8859-1") ec.primitive_convert(src="\xa4\xa2", dst="", nil, 10) p ec.primitive_errinfo #=> [:undefined_conversion, "UTF-8", "ISO-8859-1", "\xE3\x81\x82", ""] # partial character is invalid ec = Encoding::Converter.new("EUC-JP", "ISO-8859-1") ec.primitive_convert(src="\xa4", dst="", nil, 10) p ec.primitive_errinfo #=> [:incomplete_input, "EUC-JP", "UTF-8", "\xA4", ""] # Encoding::Converter::PARTIAL_INPUT prevents invalid errors by # partial characters. ec = Encoding::Converter.new("EUC-JP", "ISO-8859-1") ec.primitive_convert(src="\xa4", dst="", nil, 10, Encoding::Converter::PARTIAL_INPUT) p ec.primitive_errinfo #=> [:source_buffer_empty, nil, nil, nil, nil] # \xd8\x00\x00@ is invalid as UTF-16BE because # no low surrogate after high surrogate (\xd8\x00). # It is detected by 3rd byte (\00) which is part of next character. # So the high surrogate (\xd8\x00) is discarded and # the 3rd byte is read again later. # Since the byte is buffered in ec, it is dropped from src. ec = Encoding::Converter.new("UTF-16BE", "UTF-8") ec.primitive_convert(src="\xd8\x00\x00@", dst="", nil, 10) p ec.primitive_errinfo #=> [:invalid_byte_sequence, "UTF-16BE", "UTF-8", "\xD8\x00", "\x00"] p src #=> "@" # Similar to UTF-16BE, \x00\xd8@\x00 is invalid as UTF-16LE. # The problem is detected by 4th byte. ec = Encoding::Converter.new("UTF-16LE", "UTF-8") ec.primitive_convert(src="\x00\xd8@\x00", dst="", nil, 10) p ec.primitive_errinfo #=> [:invalid_byte_sequence, "UTF-16LE", "UTF-8", "\x00\xD8", "@\x00"] p src #=> ""
Source
static VALUE
econv_putback(int argc, VALUE *argv, VALUE self)
{
rb_econv_t *ec = check_econv(self);
int n;
int putbackable;
VALUE str, max;
if (!rb_check_arity(argc, 0, 1) || NIL_P(max = argv[0])) {
n = rb_econv_putbackable(ec);
}
else {
n = NUM2INT(max);
putbackable = rb_econv_putbackable(ec);
if (putbackable < n)
n = putbackable;
}
str = rb_str_new(NULL, n);
rb_econv_putback(ec, (unsigned char *)RSTRING_PTR(str), n);
if (ec->source_encoding) {
rb_enc_associate(str, ec->source_encoding);
}
return str;
}
Setzt die Bytes zurück, die konvertiert werden.
Die Bytes werden durch einen invalid_byte_sequence-Fehler verursacht. Bei einem invalid_byte_sequence-Fehler werden einige Bytes verworfen und einige Bytes werden zur späteren Konvertierung gepuffert. Letztere Bytes können zurückgesetzt werden. Dies kann durch Encoding::InvalidByteSequenceError#readagain_bytes und Encoding::Converter#primitive_errinfo beobachtet werden.
ec = Encoding::Converter.new("utf-16le", "iso-8859-1") src = "\x00\xd8\x61\x00" dst = "" p ec.primitive_convert(src, dst) #=> :invalid_byte_sequence p ec.primitive_errinfo #=> [:invalid_byte_sequence, "UTF-16LE", "UTF-8", "\x00\xD8", "a\x00"] p ec.putback #=> "a\x00" p ec.putback #=> "" # no more bytes to put back
Source
static VALUE
econv_get_replacement(VALUE self)
{
rb_econv_t *ec = check_econv(self);
int ret;
rb_encoding *enc;
ret = make_replacement(ec);
if (ret == -1) {
rb_raise(rb_eUndefinedConversionError, "replacement character setup failed");
}
enc = rb_enc_find(ec->replacement_enc);
return rb_enc_str_new((const char *)ec->replacement_str, (long)ec->replacement_len, enc);
}
Gibt die Ersatzzeichenkette zurück.
ec = Encoding::Converter.new("euc-jp", "us-ascii") p ec.replacement #=> "?" ec = Encoding::Converter.new("euc-jp", "utf-8") p ec.replacement #=> "\uFFFD"
Source
static VALUE
econv_set_replacement(VALUE self, VALUE arg)
{
rb_econv_t *ec = check_econv(self);
VALUE string = arg;
int ret;
rb_encoding *enc;
StringValue(string);
enc = rb_enc_get(string);
ret = rb_econv_set_replacement(ec,
(const unsigned char *)RSTRING_PTR(string),
RSTRING_LEN(string),
rb_enc_name(enc));
if (ret == -1) {
/* xxx: rb_eInvalidByteSequenceError? */
rb_raise(rb_eUndefinedConversionError, "replacement character setup failed");
}
return arg;
}
Setzt die Ersatzzeichenkette.
ec = Encoding::Converter.new("utf-8", "us-ascii", :undef => :replace) ec.replacement = "<undef>" p ec.convert("a \u3042 b") #=> "a <undef> b"
Source
static VALUE
econv_source_encoding(VALUE self)
{
rb_econv_t *ec = check_econv(self);
return econv_get_encoding(ec->source_encoding);
}
Gibt die Quellkodierung als Encoding-Objekt zurück.