From: Ryunosuke Ohshima Date: 2000-05-11T23:48:55+09:00 Subject: [ruby-list:22463] Re: pack/unpack 'w' (BER comperssed integer) ----Next_Part(Thu_May_11_23:47:17_2000_542)-- Content-Type: Text/Plain; charset=iso-2022-jp Content-Transfer-Encoding: 7bit 大島です。 [ruby-list:22451]に添付したパッチでは、packでBignumを扱っていません でした。やはりそれではまずいと思いまして、packでもBignumを扱えるよう にしました。最後にそのパッチを添付しておきます。([ruby-list:22451]の パッチは当てずに、直接にこのパッチを当ててください。) From: Takayuki YAMAGUCHI Subject: [ruby-list:22461] Re: pack/unpack 'w' (BER comperssed integer) Date: Thu, 11 May 2000 19:22:52 +0900 > At 12:56 +0900 2000.5.11, Ryunosuke Ohshima wrote: > >Namazuのインデックスの読み出しに、BER圧縮整数値の変換が必要になりま > >した。Perlではpack/unpackの'w'テンプレートによってこの変換が実装され > >ているので、試しにRubyに実装してみました。 > > 有り難うございます_o_ > #いきなり押し付けてしまって申し訳なかったです >ところでBERって何の略なのでしょうか?perlとpnamazuのソースを参考にし > >て実装したもので、BER圧縮整数値自体についての明確な文献は見つけられ > >ませんでした。 > > 現実逃避ついでに調べてみました > Basic Encoding Rulesの略で、ASN.1の符号化規則の一つだそうです。 > > http://www.intap.or.jp/oiia/cont1/p0302.html{0recid=10760.html > あたりに簡単な説明があります。 ありがとうございます。ISOが定めている規格でしたか。売り物だから、Web では直接の情報がみつからなかったのか。 > P.S.rbnamazuの方、よろしくお願いします>大島さん どれだけご期待に添えるかわかりませんが、できる部分はやってみます。もっ とも、単語毎の得点を取り出して、ページの得点を算出する部分しか出来て いないです。まだバギーですし。 大島 龍之介 ryu@jaist.ac.jp ----Next_Part(Thu_May_11_23:47:17_2000_542)-- Content-Type: Text/Plain; charset=us-ascii Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="ruby_pack.patch" diff -ru ruby_orig/bignum.c ruby/bignum.c --- ruby_orig/bignum.c Thu May 11 22:47:30 2000 +++ ruby/bignum.c Thu May 11 22:51:05 2000 @@ -944,7 +944,7 @@ return rb_big_modulo(x, y, 0); } -static VALUE +VALUE rb_big_divmod(x, y) VALUE x, y; { diff -ru ruby_orig/intern.h ruby/intern.h --- ruby_orig/intern.h Thu May 11 22:47:30 2000 +++ ruby/intern.h Thu May 11 22:51:05 2000 @@ -68,6 +68,7 @@ VALUE rb_big_plus _((VALUE, VALUE)); VALUE rb_big_minus _((VALUE, VALUE)); VALUE rb_big_mul _((VALUE, VALUE)); +VALUE rb_big_divmod _((VALUE, VALUE)); VALUE rb_big_pow _((VALUE, VALUE)); VALUE rb_big_and _((VALUE, VALUE)); VALUE rb_big_or _((VALUE, VALUE)); diff -ru ruby_orig/pack.c ruby/pack.c --- ruby_orig/pack.c Thu May 11 22:47:30 2000 +++ ruby/pack.c Thu May 11 23:33:04 2000 @@ -843,6 +843,53 @@ } break; + case 'w': + while (len-- > 0) { + unsigned long ul; + VALUE buf = rb_str_new(0, 0); + char c, *bufs, *bufe; + + from = NEXTFROM; + + if (TYPE(from) == T_BIGNUM) { + VALUE big128 = rb_uint2big(128); + while (TYPE(from) == T_BIGNUM) { + from = rb_big_divmod(from, big128); + c = NUM2INT(RARRAY(from)->ptr[1]) | 0x80; /* mod */ + rb_str_cat(buf, &c, sizeof(char)); + from = RARRAY(from)->ptr[0]; /* div */ + } + } + + if (NIL_P(from)) ul = 0; + else { + ul = NUM2ULONG(from); + } + + while (ul) { + c = ((ul & 0x7f) | 0x80); + rb_str_cat(buf, &c, sizeof(char)); + ul >>= 7; + } + + if (RSTRING(buf)->len) { + bufs = RSTRING(buf)->ptr; + bufe = bufs + RSTRING(buf)->len - 1; + *bufs &= 0x7f; /* clear continue bit */ + while (bufs < bufe) { /* reverse */ + c = *bufs; + *bufs++ = *bufe; + *bufe-- = c; + } + rb_str_cat(res, RSTRING(buf)->ptr, RSTRING(buf)->len); + } + else { + c = 0; + rb_str_cat(res, &c, sizeof(char)); + } + } + break; + default: break; } @@ -1569,6 +1616,37 @@ rb_str_cat2(str, t); } rb_ary_push(ary, str); + } + } + break; + + case 'w': + { + unsigned long ul = 0; + unsigned long ulmask = 0xfe << ((sizeof(unsigned long) - 1) * 8); + + while (len > 0 && s < send) { + ul <<= 7; + ul |= (*s & 0x7f); + if (!(*s++ & 0x80)) { + rb_ary_push(ary, rb_uint2inum(ul)); + len--; + ul = 0; + } + else if (ul & ulmask) { + VALUE big = rb_uint2big(ul); + VALUE big128 = rb_uint2big(128); + while (s < send) { + big = rb_big_mul(big, big128); + big = rb_big_plus(big, rb_uint2big(*s & 0x7f)); + if (!(*s++ & 0x80)) { + rb_ary_push(ary, big); + len--; + ul = 0; + break; + } + } + } } } break; ----Next_Part(Thu_May_11_23:47:17_2000_542)----