Revision: 3811 http://trac.macosforge.org/projects/ruby/changeset/3811 Author: lsansonetti@apple.com Date: 2010-03-18 16:06:14 -0700 (Thu, 18 Mar 2010) Log Message: ----------- fixed some bugs in Numeric#chr Modified Paths: -------------- MacRuby/trunk/include/ruby/encoding.h MacRuby/trunk/numeric.c MacRuby/trunk/sprintf.c Modified: MacRuby/trunk/include/ruby/encoding.h =================================================================== --- MacRuby/trunk/include/ruby/encoding.h 2010-03-18 22:02:12 UTC (rev 3810) +++ MacRuby/trunk/include/ruby/encoding.h 2010-03-18 23:06:14 UTC (rev 3811) @@ -126,8 +126,6 @@ void rb_enc_set_default_external(VALUE encoding); long rb_memsearch(const void*,long,const void*,long,rb_encoding*); -VALUE rb_num_to_chr(VALUE, rb_encoding *); - RUBY_EXTERN VALUE rb_cEncoding; static inline int Modified: MacRuby/trunk/numeric.c =================================================================== --- MacRuby/trunk/numeric.c 2010-03-18 22:02:12 UTC (rev 3810) +++ MacRuby/trunk/numeric.c 2010-03-18 23:06:14 UTC (rev 3811) @@ -19,7 +19,10 @@ #include <ruby/node.h> #include "vm.h" #include "id.h" +#include "encoding.h" +#include <unicode/utf8.h> + #ifdef HAVE_FLOAT_H #include <float.h> #endif @@ -1919,29 +1922,6 @@ return rb_vm_call(num, selMINUS, 1, &one, false); } -VALUE -rb_num_to_chr(VALUE num, rb_encoding *enc) -{ - // XXX completely broken - long i = NUM2LONG(num); - char c[2] = {i, '\0'}; - - if (enc) { - return rb_enc_str_new(c, 1, enc); - } - else { - if (i < 0 || 0xff < i) { - rb_raise(rb_eRangeError, "%"PRIdVALUE " out of char range", i); - } - if (i < 0x80) { - return rb_usascii_str_new(c, 1); - } - else { - return rb_str_new(c, 1); - } - } -} - /* * call-seq: * int.chr([encoding]) => string @@ -1957,10 +1937,79 @@ static VALUE int_chr(VALUE num, SEL sel, int argc, VALUE *argv) { - if (argc > 1) { - rb_raise(rb_eArgError, "wrong number of arguments (%d for 0 or 1)", argc); + long i = NUM2LONG(num); + rb_encoding_t *enc = NULL; + + switch (argc) { + case 0: + if (i < 0) { +out_of_range: + rb_raise(rb_eRangeError, "%"PRIdVALUE " out of char range", i); + } + if (0xff < i) { + goto decode; + } + else { + char c = (char)i; + if (i < 0x80) { + return rb_usascii_str_new(&c, 1); + } + return rb_bstr_new_with_data((uint8_t *)&c, 1); + } + break; + + case 1: + break; + + default: + rb_raise(rb_eArgError, "wrong number of arguments (%d for 0 or 1)", + argc); } - return rb_num_to_chr(num, (argc ? rb_to_encoding(argv[0]) : NULL)); + + enc = rb_to_encoding(argv[0]); + +decode: + if (i < 0 || i > UINT_MAX) { + goto out_of_range; + } + + if (enc == NULL) { + enc = rb_encodings[ENCODING_BINARY]; + } + + if (enc == rb_encodings[ENCODING_BINARY]) { + uint8_t c = (uint8_t)i; + return rb_bstr_new_with_data(&c, 1); + } + + if (enc == rb_encodings[ENCODING_ASCII]) { + if (i >= 0x80) { + goto out_of_range; + } + char c = (char)i; + return rb_enc_str_new(&c, 1, enc); + } + + if (enc == rb_encodings[ENCODING_UTF8]) { + const int bytelen = U8_LENGTH(i); + if (bytelen <= 0) { + goto out_of_range; + } + uint8_t *buf = (uint8_t *)malloc(bytelen); + int offset = 0; + UBool error = false; + U8_APPEND(buf, offset, bytelen, i, error); + if (error) { + free(buf); + goto out_of_range; + } + VALUE str = rb_enc_str_new((char *)buf, bytelen, enc); + free(buf); + return str; + } + + rb_raise(rb_eArgError, "encoding `%s' not supported yet", + RSTRING_PTR(rb_inspect((VALUE)enc))); } static VALUE Modified: MacRuby/trunk/sprintf.c =================================================================== --- MacRuby/trunk/sprintf.c 2010-03-18 22:02:12 UTC (rev 3810) +++ MacRuby/trunk/sprintf.c 2010-03-18 23:06:14 UTC (rev 3811) @@ -628,9 +628,13 @@ arg = rb_str_substr(arg, 0, 1); } else { - // rb_num_to_chr is broken so leave out the - // enc or we don't get range checking - arg = rb_num_to_chr(arg, NULL /*rb_enc_get(fmt)*/); + long num = NUM2LONG(arg); + if (num < 0 || i > 0xff) { + rb_raise(rb_eRangeError, "%ld out of char range", + num); + } + char c = (char)num; + arg = rb_str_new(&c, 1); } complete = true; break;
participants (1)
-
source_changes@macosforge.org