[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