Skip to content

Commit

Permalink
fixed some bugs in Numeric#chr
Browse files Browse the repository at this point in the history
git-svn-id: http://svn.macosforge.org/repository/ruby/MacRuby/trunk@3811 23306eb0-4c56-4727-a40e-e92c0eb68959
  • Loading branch information
lrz committed Mar 18, 2010
1 parent 423e34a commit 110e345
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 31 deletions.
2 changes: 0 additions & 2 deletions include/ruby/encoding.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,6 @@ VALUE rb_enc_default_external(void);
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
Expand Down
101 changes: 75 additions & 26 deletions numeric.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@
#include <ruby/node.h>
#include "vm.h"
#include "id.h"
#include "encoding.h"

#include <unicode/utf8.h>

#ifdef HAVE_FLOAT_H
#include <float.h>
Expand Down Expand Up @@ -1919,29 +1922,6 @@ int_pred(VALUE num, SEL sel)
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
Expand All @@ -1957,10 +1937,79 @@ rb_num_to_chr(VALUE num, rb_encoding *enc)
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);
}

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);
}
return rb_num_to_chr(num, (argc ? rb_to_encoding(argv[0]) : NULL));

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
Expand Down
10 changes: 7 additions & 3 deletions sprintf.c
Original file line number Diff line number Diff line change
Expand Up @@ -628,9 +628,13 @@ rb_str_format(int argc, const VALUE *argv, VALUE fmt)
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;
Expand Down

0 comments on commit 110e345

Please sign in to comment.