Byte strings

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

On 2013-09-08, at 3:28 AM, Charles H. [email protected]
wrote:

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)?

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

Mike S. [email protected]
http://www.stok.ca/~mike/

The “`Stok’ disclaimers” apply.

I just glanced at this, but it looks like you are trying to do this…

p RUBY_VERSION

v = “abcdef”
v[2] = 5 # try 5.to_s ?
p v

Harry

On 09/07/2013 08:31 PM, Mike S. wrote:

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”

On 09/07/2013 08:46 PM, Harry K. wrote:

Harry

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.

v[i] = r unless r == 0

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