On 09/07/2013 08:31 PM, Mike Stok wrote:
> On 2013-09-08, at 3:28 AM, Charles Hixson <charleshixsn / earthlink.net> wrote:
>
>> It appears that in Ruby2.0 it's impossible to treat strings as mutable byte arrays.  Is there any replacement?
>>
>> FWIW, the string is initialized with:
>> v    =    ["00" * len].pack("H*")
>> and trouble is caused at:
>>             q,r    =    q.divmod(128)
>>             p("q = #{q}, r = #{r}")
>>             v[i]    =    r
>> Where I am told:
>> "q = 8, r = 0"
>> test.rb:54:in `[]=': no implicit conversion of Fixnum into String (TypeError)
>>
>> a test modification to see if 0 was being handled specially:
>>             v[i]    =    r        unless r == 0
>> yielded:
>> "q = 8, r = 0"
>> "q = 0, r = 8"
>> test.rb:54:in `[]=': no implicit conversion of Fixnum into String (TypeError)
>>
>> even though 0x08 is a valid ASCII code (backspace).
>>
>> In more detail, the code was:
>>     def    i2key(int, len = 18)
>>         if    not    len.is_a?(Fixnum)    then
>>             raise    TypeError, "len not a Fixnum, == #{len.inspect}"
>>         end    #if
>>         if    len < 2    then
>>             raise    ArgumentError, "len too small, == #{len}"
>>         end    #if
>>         if    not    int.is_a?(Integer)    then
>>             raise    TypeError, "int not an Integer, == #{int.inspect}"
>>         end    #if
>>         if    int < 0    then
>>             raise    ArgumentError, "int too small, == #{int}"
>>         end    #if
>>         v    =    ["00" * len].pack("H*")
>>         i    =    len
>>         q    =    int
>>         while    (q > 0    and    i > 0)
>>             i    =    i - 1
>>             q,r    =    q.divmod(128)
>>             p("q = #{q}, r = #{r}")
>>             v[i]    =    r        unless r == 0
>>         end    #while
>>         return    v
>>     end    #i2key
> Have you considered using String#getbyte(index) and String#setbyte(index, integer)?
>
> http://ruby-doc.org/core-2.0.0/String.html#method-i-getbyte
> http://ruby-doc.org/core-2.0.0/String.html#method-i-setbyte
>
> ratdog:~ mike$ pry
> [1] pry(main)> str = ['00' * 10].pack('H*')
> => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
> [2] pry(main)> str.setbyte(5, 8)
> => 8
> [3] pry(main)> str.getbyte(5)
> => 8
> [4] pry(main)> str
> => "\x00\x00\x00\x00\x00\b\x00\x00\x00\x00"
> [5] pry(main)> RUBY_VERSION
> => "2.0.0"
>
> Hope this helps,
>
> Mike
>
Thanks.  Those were the routines I needed to know about.  I can't really 
test it until I write the inverse function, but inspection of the 
results for:
             #v[i]    =    r        unless r == 0
             v.setbyte(i, r)
looks quite good.  Checking individual numbers gives the expected values.
1
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01"
2
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02"
3
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03"
4
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04"
8
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\b"
16
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10"


-- 
Charles Hixson