[Aversa-commits] aversa/ext BEncoding.c test_BEncoding.rb
teamikl at rubyforge.org
teamikl at rubyforge.org
Tue Sep 21 13:03:20 EDT 2004
Update of /var/cvs/aversa/aversa/ext
In directory rubyforge.org:/tmp/cvs-serv4656
Modified Files:
BEncoding.c test_BEncoding.rb
Log Message:
Fixed segmentation fault, was initialize of buffer.
I had excepted xrealloc does, but it was not sure.
Index: BEncoding.c
===================================================================
RCS file: /var/cvs/aversa/aversa/ext/BEncoding.c,v
retrieving revision 1.9
retrieving revision 1.10
diff -C2 -d -r1.9 -r1.10
*** BEncoding.c 15 Sep 2004 16:12:50 -0000 1.9
--- BEncoding.c 21 Sep 2004 17:03:18 -0000 1.10
***************
*** 4,29 ****
* BEncoding module
*
! * === HOW TO COMPILE (GCC)
*
! * > ruby -rmkmf -e 'create_makefile("_bencoding")'
* > make
*
* === HOW TO USE
*
! * > ls
! * _bencoding.so
! * > irb
! * irb(main):001:0> require '_bencoding'
! * true
! * irb(main):002:0> BEncoding.encode({'a' => [1, 2, 3]})
! * => "d1:all1el2el3eee"
*
*
* ./ext/bencoding.rb is the interface for _bencoding.so. It's more useful.
*
! * irb(main):003:0> require 'bencoding'
! * true
! * irb(main):004:0> "Hello, world".bencode
! * => "12:Hello, world"
*
*
--- 4,29 ----
* BEncoding module
*
! * === HOW TO COMPILE
*
! * > ruby ./extconf.rb
* > make
*
* === HOW TO USE
*
! * > ls
! * _bencoding.so
! * > irb
! * irb(main):001:0> require '_bencoding'
! * true
! * irb(main):002:0> BEncoding.encode({'a' => [1, 2, 3]})
! * => "d1:all1el2el3eee"
*
*
* ./ext/bencoding.rb is the interface for _bencoding.so. It's more useful.
*
! * irb(main):003:0> require 'bencoding'
! * true
! * irb(main):004:0> "Hello, world".bencode
! * => "12:Hello, world"
*
*
***************
*** 33,37 ****
*
* - object.c rb_inspect ... return printable string of an object.
! * - marshal.c ... similar like b-encoding. (pstore use)
*
*
--- 33,37 ----
*
* - object.c rb_inspect ... return printable string of an object.
! * - marshal.c ... similar like b-encoding. (pstore use)
*
*
***************
*** 49,65 ****
* - TODO implement decode function.
* - TODO check error cases.
! * - TODO check memory leak, I don't understand ruby' GC yet.
! *
! *
! * === BUGS
! *
! * - FIXME Segmentation fault when loop many times.
! *
! * OK: 1.upto(1000){ BEncoding.encode(data) }
! * NG: 1.upto(100000){ BEncoding.encode(data) }
! *
! *
! * I needed GC to mark the object which I made it on heap by rb_funcall()
! * But, no need to mark FIXNUM, ID, Qnil, Qtreu, Qfalse, and VALUE on stack.
*
*
--- 49,53 ----
* - TODO implement decode function.
* - TODO check error cases.
! * - TODO check if ruby string contains null string.
*
*
***************
*** 71,82 ****
*/
-
- #include <string.h>
#include "ruby.h"
#include "rubyio.h"
/* BT prefix for Bencoding Type */
! #define BT_DICTIONARY 'd' /* Dictionary is a Hash in Ruby */
! #define BT_LIST 'l' /* List is an Array in Ruby */
#define BT_INTEGER 'i'
#define BT_STRING_SEPARATOR ':'
--- 59,68 ----
*/
#include "ruby.h"
#include "rubyio.h"
/* BT prefix for Bencoding Type */
! #define BT_DICTIONARY 'd' /* Dictionary is a Hash in Ruby */
! #define BT_LIST 'l' /* List is an Array in Ruby */
#define BT_INTEGER 'i'
#define BT_STRING_SEPARATOR ':'
***************
*** 98,225 ****
static unsigned long
bencoding_encode_len(obj, nesting_level)
! VALUE obj;
! int nesting_level;
{
! register int i = 0;
! unsigned long len = 0;
! size_t tmp1 = 0;
! size_t tmp2 = 0;
! volatile VALUE ary = Qnil;
! volatile VALUE tmp = Qnil;
- if (nesting_level > MAXIMUM_RECURSION_DEPTH)
- rb_raise(rb_eRuntimeError, "Maximum recursion depth exceeded");
! switch (TYPE(obj)) {
! case T_HASH:
! tmp = rb_funcall(obj, id_to_a, 0, 0); rb_gc_mark(tmp);
! ary = rb_funcall(tmp, id_sort, 0, 0); rb_gc_mark(ary);
! for (i = 0; i < RARRAY(ary)->len; ++i)
! {
! tmp = RARRAY(ary)->ptr[i];
! len += bencoding_encode_len(RARRAY(tmp)->ptr[0], nesting_level+1);
! len += bencoding_encode_len(RARRAY(tmp)->ptr[1], nesting_level+1);
! }
! len += 2;
! break;
!
! case T_ARRAY:
! for (i = 0; i < RARRAY(obj)->len; ++i)
! {
! len += bencoding_encode_len(RARRAY(obj)->ptr[i], nesting_level+1);
! }
! len += 2;
! break;
!
! case T_FIXNUM:
! case T_BIGNUM:
! tmp = rb_funcall(obj, id_to_s, 0, 0); rb_gc_mark(tmp);
! len += RSTRING(tmp)->len + 2;
! break;
!
! case T_STRING: /* TODO refactoring variables names are ... */
! tmp1 = RSTRING(obj)->len;
! tmp = rb_funcall(INT2NUM(tmp1), id_to_s, 0, 0); rb_gc_mark(tmp);
! tmp2 = RSTRING(tmp)->len;
! len += tmp2 + 1 + tmp1;
! break;
!
! default:
! rb_raise(rb_eTypeError, "No support type");
! break;
! }
!
! return len;
}
/**
! *
! *
! *
*/
static char *
bencoding_encode_iterator(stream, obj)
! char *stream;
! VALUE obj;
{
! volatile VALUE tmp = Qnil;
! volatile VALUE ary = Qnil;
! register int i = 0;
! unsigned long len = 0;
! unsigned long pre = 0;
!
! switch (TYPE(obj)) {
! case T_HASH: /* T_HASH == BT_DICTIONARY */
! /* aryObj = obj.to_a.sort */
! tmp = rb_funcall(obj, id_to_a, 0, 0); rb_gc_mark(tmp);
! ary = rb_funcall(tmp, id_sort, 0, 0); rb_gc_mark(ary);
! *stream++ = BT_DICTIONARY;
! for (i = 0; i < RARRAY(ary)->len; ++i)
! {
! tmp = RARRAY(ary)->ptr[i];
! stream = bencoding_encode_iterator(stream, RARRAY(tmp)->ptr[0]);
! stream = bencoding_encode_iterator(stream, RARRAY(tmp)->ptr[1]);
! }
! *stream++ = BT_END;
! break;
!
! case T_ARRAY: /* T_ARRAY == BT_LIST */
! *stream++ = BT_LIST;
! for (i = 0; i < RARRAY(obj)->len; ++i)
! {
! stream = bencoding_encode_iterator(stream, RARRAY(obj)->ptr[i]);
! }
! *stream++ = BT_END;
! break;
! case T_FIXNUM:
! case T_BIGNUM:
! tmp = rb_funcall(obj, id_to_s, 0, 0); rb_gc_mark(tmp);
! len = RSTRING(tmp)->len;
! *stream++ = BT_INTEGER;
! strncat(stream, StringValuePtr(tmp), len);
! stream += len;
! *stream++ = BT_END;
! break;
! case T_STRING:
! /* RSTRING()->ptr => StringValueCStr */
! len = RSTRING(obj)->len;
! tmp = rb_funcall(INT2NUM(len), id_to_s, 0, 0); rb_gc_mark(tmp);
! pre = RSTRING(tmp)->len;
! strncat(stream, StringValuePtr(tmp), pre);
! stream += pre;
! *stream++ = BT_STRING_SEPARATOR;
! strncat(stream, StringValuePtr(obj), len);
! stream += len;
! break;
!
! default:
! rb_raise(rb_eTypeError, "No Support type");
! break;
! }
! return stream;
}
--- 84,221 ----
static unsigned long
bencoding_encode_len(obj, nesting_level)
! VALUE obj;
! int nesting_level;
{
! register int i = 0;
! unsigned long len = 0;
! size_t tmp1 = 0;
! size_t tmp2 = 0;
! volatile VALUE ary = Qnil;
! volatile VALUE tmp = Qnil;
! if (nesting_level > MAXIMUM_RECURSION_DEPTH)
! rb_raise(rb_eRuntimeError, "Maximum recursion depth exceeded");
!
! switch (TYPE(obj)) {
! case T_HASH:
! tmp = rb_funcall(obj, id_to_a, 0, 0); rb_gc_mark(tmp);
! ary = rb_funcall(tmp, id_sort, 0, 0); rb_gc_mark(ary);
! for (i = 0; i < RARRAY(ary)->len; ++i)
! {
! tmp = RARRAY(ary)->ptr[i];
! len += bencoding_encode_len(RARRAY(tmp)->ptr[0], nesting_level+1);
! len += bencoding_encode_len(RARRAY(tmp)->ptr[1], nesting_level+1);
! }
! len += 2;
! break;
!
! case T_ARRAY:
! for (i = 0; i < RARRAY(obj)->len; ++i)
! {
! len += bencoding_encode_len(RARRAY(obj)->ptr[i], nesting_level+1);
! }
! len += 2;
! break;
!
! case T_FIXNUM:
! case T_BIGNUM:
! tmp = rb_funcall(obj, id_to_s, 0, 0); rb_gc_mark(tmp);
! len += RSTRING(tmp)->len + 2;
! break;
!
! case T_STRING:
! /* TODO refactoring variables names are ... */
! /* XXX Do I need to mark if INT2NUM return Bignum? */
! tmp1 = RSTRING(obj)->len;
! tmp = rb_funcall(INT2NUM(tmp1), id_to_s, 0, 0); rb_gc_mark(tmp);
! tmp2 = RSTRING(tmp)->len;
! len += tmp2 + 1 + tmp1;
! break;
!
! default:
! rb_raise(rb_eTypeError, "No support type");
! break;
! }
!
! return len;
}
/**
! * bencoding_encode_iterator(stream, obj) => stream
*/
static char *
bencoding_encode_iterator(stream, obj)
! char *stream;
! VALUE obj;
{
! volatile VALUE tmp = Qnil;
! volatile VALUE ary = Qnil;
! register int i = 0;
! unsigned long len = 0;
! unsigned long pre = 0;
!
! switch (TYPE(obj)) {
! case T_HASH: /* T_HASH == BT_DICTIONARY */
! /* ary = obj.to_a.sort */
! tmp = rb_funcall(obj, id_to_a, 0, 0); rb_gc_mark(tmp);
! ary = rb_funcall(tmp, id_sort, 0, 0); rb_gc_mark(ary);
! /* stream += 'd' + ary.map{|k,v| k.bencode + v.bencode}.join + 'e' */
! *stream++ = BT_DICTIONARY;
! for (i = 0; i < RARRAY(ary)->len; ++i)
! {
! tmp = RARRAY(ary)->ptr[i];
! stream = bencoding_encode_iterator(stream, RARRAY(tmp)->ptr[0]);
! stream = bencoding_encode_iterator(stream, RARRAY(tmp)->ptr[1]);
! }
! *stream++ = BT_END;
! break;
! case T_ARRAY: /* T_ARRAY == BT_LIST */
!
! /* stream += 'l' + obj.map{|i| i.bencode}.join + 'e' */
! *stream++ = BT_LIST;
! for (i = 0; i < RARRAY(obj)->len; ++i)
! {
! stream = bencoding_encode_iterator(stream, RARRAY(obj)->ptr[i]);
! }
! *stream++ = BT_END;
! break;
!
! case T_FIXNUM:
! case T_BIGNUM:
!
! /* stream += 'i' + obj.to_s + 'e' */
! tmp = rb_funcall(obj, id_to_s, 0, 0); rb_gc_mark(tmp);
! len = RSTRING(tmp)->len;
! *stream++ = BT_INTEGER;
! strncat(stream, StringValuePtr(tmp), len);
! stream += len;
! *stream++ = BT_END;
! break;
!
! case T_STRING:
! /* RSTRING()->ptr => StringValueCStr */
! /* XXX Do I need to mark if INT2NUM return Bignum? */
! /* XXX If ruby string had null string -> strncat */
! len = RSTRING(obj)->len;
! tmp = rb_funcall(INT2NUM(len), id_to_s, 0, 0); rb_gc_mark(tmp);
! pre = RSTRING(tmp)->len;
! strncat(stream, StringValuePtr(tmp), pre);
! stream += pre;
! *stream++ = BT_STRING_SEPARATOR;
! strncat(stream, StringValuePtr(obj), len);
! stream += len;
! break;
!
! default:
! rb_raise(rb_eTypeError, "No Support type");
! break;
! }
!
! return stream;
}
***************
*** 229,243 ****
static VALUE
bencoding_encode(self, obj)
! VALUE self;
! VALUE obj;
{
! VALUE retObj = Qnil;
! unsigned long buffer_size = bencoding_encode_len(obj, 0);
! char *stream = (char *)xrealloc(0x000, buffer_size+1);
! (void)bencoding_encode_iterator(stream, obj);
! retObj = rb_str_new(stream, buffer_size); rb_gc_mark(retObj);
! /* XXX Should I xfree(stream); ??? */
! return retObj;
}
--- 225,243 ----
static VALUE
bencoding_encode(self, obj)
! VALUE self;
! VALUE obj;
{
! VALUE retObj = Qnil;
! unsigned long buffer_size = 0;
! char *stream = NULL;
!
! buffer_size = bencoding_encode_len(obj, 0);
! stream = (char *)xmalloc(buffer_size+1);
! memset(stream, 0, buffer_size+1);
!
! (void)bencoding_encode_iterator(stream, obj);
! retObj = rb_str_new(stream, buffer_size);
! return retObj;
}
***************
*** 247,279 ****
static VALUE
bencoding_decode(argc, argv)
! int argc;
! VALUE *argv;
{
! VALUE stream = Qnil;
! rb_raise(rb_eNotImpError, "Not much motivation for this method :p");
!
!
! rb_scan_args(argc, argv, "1", &stream);
! rb_gc_mark(stream);
! if (argc != 1) {
! rb_raise(rb_eArgError,
! "Wrong numbers of arguments (%d for 1)", argc);
! }
!
! /* Accept any stream object which has 'getc' and 'read' methods */
! if (rb_respond_to(stream, id_getc) &&
! rb_respond_to(stream, id_read)) {
! }
! else {
! rb_raise(rb_eTypeError,
! "Wrong argument type (require File or StringIO)");
! }
! return stream;
}
--- 247,279 ----
static VALUE
bencoding_decode(argc, argv)
! int argc;
! VALUE *argv;
{
! VALUE stream = Qnil;
! rb_raise(rb_eNotImpError, "Not much motivation for this method :p");
!
!
! rb_scan_args(argc, argv, "1", &stream);
! rb_gc_mark(stream);
! if (argc != 1) {
! rb_raise(rb_eArgError,
! "Wrong numbers of arguments (%d for 1)", argc);
! }
!
! /* Accept any stream object which has 'getc' and 'read' methods */
! if (rb_respond_to(stream, id_getc) &&
! rb_respond_to(stream, id_read)) {
! }
! else {
! rb_raise(rb_eTypeError,
! "Wrong argument type (require File or StringIO)");
! }
! return stream;
}
***************
*** 282,297 ****
Init__bencoding(void)
{
! VALUE rb_mBEncoding = rb_define_module("BEncoding");
! rb_define_module_function(rb_mBEncoding, "encode", bencoding_encode, 1);
! // rb_define_module_function(rb_mBEncoding, "decode", bencoding_decode, -1);
! id_to_s = rb_intern("to_s");
! id_to_a = rb_intern("to_a");
! id_sort = rb_intern("sort");
! id_getc = rb_intern("getc");
! id_read = rb_intern("read");
! id_concat = rb_intern("concat");
}
/* $Id$ */
--- 282,298 ----
Init__bencoding(void)
{
! VALUE rb_mBEncoding = rb_define_module("BEncoding");
! rb_define_module_function(rb_mBEncoding, "encode", bencoding_encode, 1);
! // rb_define_module_function(rb_mBEncoding, "decode", bencoding_decode, -1);
! id_to_s = rb_intern("to_s");
! id_to_a = rb_intern("to_a");
! id_sort = rb_intern("sort");
! id_getc = rb_intern("getc");
! id_read = rb_intern("read");
! id_concat = rb_intern("concat");
}
+ /* vim: filetype=c tabstop=4 shiftwidth=4 */
/* $Id$ */
Index: test_BEncoding.rb
===================================================================
RCS file: /var/cvs/aversa/aversa/ext/test_BEncoding.rb,v
retrieving revision 1.4
retrieving revision 1.5
diff -C2 -d -r1.4 -r1.5
*** test_BEncoding.rb 11 Sep 2004 16:00:53 -0000 1.4
--- test_BEncoding.rb 21 Sep 2004 17:03:18 -0000 1.5
***************
*** 8,22 ****
def test_respond_to
! warn "
!
! \e[1m\e[41m !!! WARNING !!! IMPORTANT NOTES \e[0m
!
! This is very dangerous. Maybe the C extension breakes memory...
! When comment out this assert_respond_to, failed and effect to other tests.
! Not only failed in this test. So, \e[1m BEncoding.c is not safe \e[0m yet.
!
! ".gsub(/^\s{4}/m,'')
!
! # assert_respond_to(0, :bencode)
end
--- 8,16 ----
def test_respond_to
! assert_respond_to(:bencode, 0)
! assert_respond_to(:bencode, "string")
! assert_respond_to(:bencode, [1,2,3])
! assert_respond_to(:bencode, {"foo"=>"bar"})
! assert_respond_to(:bencode, 1000000000000000000000000) # Bignum
end
More information about the Aversa-commits
mailing list