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
test.rb:54:in `[]=’: no implicit conversion of Fixnum into String (TypeError)
In more detail, the code was:
if int < 0 then
end #while
return v
end #i2key
Have you considered using String#getbyte(index) and
String#setbyte(index, integer)?
Where I am told:
even though 0x08 is a valid ASCII code (backspace).
raise TypeError, “int not an Integer, == #{int.inspect}”
p(“q = #{q}, r = #{r}”)
[1] pry(main)> str = [‘00’ * 10].pack(‘H*’)
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”
Sorry, but I want to set the ASCII char whose value is 5. A 64 bit
Fixnum can be held in 9 bytes if you can code it mod 128. Using
standard string translation can take over twice as many. (I didn’t
calculate it exactly, but lots more. Since the key value is to
determine the sort order, I can’t use the standard pack(“w”) routine,
either. That produces a string without leading zeros, which won’t sort
correctly.
This line looked odd to me when I glanced through.
In this line, if r is a Fixnum then you are trying to put a Fixnum into
a
String v[i].
If r is a String then when will r == 0 ?
I did not read all of your code, I just looked at the error location
first.
Harry
This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.