Skip to content
Browse files

Amending specs for Array#pack('U')

* rbx is now passing most specs
* failing specs are due to String#unpack.

Signed-off-by: Brian Ford <bford@engineyard.com>
  • Loading branch information...
1 parent 328c40e commit b239a3b615d341f982a7a4a3a1b1200d95f79684 @ashelly ashelly committed with Brian Ford Feb 27, 2008
Showing with 69 additions and 10 deletions.
  1. +44 −0 kernel/core/array.rb
  2. +25 −10 spec/ruby/1.8/core/array/pack_spec.rb
View
44 kernel/core/array.rb
@@ -906,6 +906,7 @@ def self.after_loaded
BASE_64_ALPHA[63] = ?/
end
+
# TODO fill out pack.
def pack(schema)
# The schema is an array of arrays like [["A", "6"], ["u", "*"], ["X", ""]]. It represents the parsed
@@ -1169,6 +1170,47 @@ def pack(schema)
arr_idx += 1
ret << str
+
+ elsif kind == 'U'
+ #converts the number passed, or all for * or 1 if missing
+ count = !t ? 1 : (t == "*" ? self.size-arr_idx : t.to_i)
+ raise ArgumentError, "too few array elements" if arr_idx + count > self.length
+
+ count.times do
+ item = Type.coerce_to(self[arr_idx], Integer, :to_i)
+ raise RangeError, "pack(U): value out of range" if item < 0
+ #handle the simple case and move on
+ if item < 0x80
+ ret << item
+ i=0
+ #else count the bytes needed
+ elsif item < 0x800
+ i = bytes = 2
+ elsif item < 0x10000
+ i = bytes = 3
+ elsif item < 0x200000
+ i = bytes = 4
+ elsif item < 0x4000000
+ i = bytes = 5
+ elsif item <= 0x7FFFFFFF
+ i = bytes = 6
+ else
+ raise RangeError, "pack(U): value out of range"
+ end
+ if i>0
+ #make room
+ ret<<' '*bytes
+ #fill backwards: put the least significant bits at the end
+ # shift the next set down, and repeat
+ while 0 < i-=1
+ ret[i-bytes] = (item | 0x80) & 0xBF
+ item >>= 6
+ end
+ #catch the highest bits - the mask depends on the byte count
+ ret[-bytes] = (item | ((0x3F00>>bytes)) & 0xFC)
+ end
+ arr_idx += 1
+ end
else
raise ArgumentError, "Unknown kind #{kind}"
end
@@ -1907,3 +1949,5 @@ def isort_block!(left, right, block)
private :qsort_block
private :isort_block
end
+
+
View
35 spec/ruby/1.8/core/array/pack_spec.rb
@@ -600,20 +600,35 @@ class X; def to_s; "unnamed object"; end; end
end
it "converts integers into UTF-8 encoded byte sequences with ('U')" do
+ numbers = [0, 1, 15, 16, 127,
+ 128, 255, 256, 1024]
+ numbers.each do |n|
+ [n].pack('U').unpack('U').should == [n]
+ end
+ [0x7F, 0x7F].pack('U*').should == "\x7F\x7F"
+ [262193, 4736, 191, 12, 107].pack('U*').should == "\xF1\x80\x80\xB1\xE1\x8A\x80\xC2\xBF\x0C\x6B"
+ [2**16+1, 2**30].pack('U2').should == "\360\220\200\201\375\200\200\200\200\200"
+
+ lambda { [].pack('U') }.should raise_error(ArgumentError)
+ lambda { [1].pack('UU') }.should raise_error(ArgumentError)
+ lambda { [2**32].pack('U') }.should raise_error(RangeError)
+ lambda { [-1].pack('U') }.should raise_error(RangeError)
+ lambda { [-5].pack('U') }.should raise_error(RangeError)
+ lambda { [-2**32].pack('U') }.should raise_error(RangeError)
+ end
+
+ it "only takes as many elements as specified after ('U')" do
+ [?a,?b,?c].pack('U2').should == "ab"
+ end
+
+ it "converts big integers into UTF-8 encoded byte sequences with ('U')" do
+ #these are actually failing on String#unpack
+ # they are not passing the 'utf8_regex_strict' test
compliant_on :ruby, :jruby do
- numbers = [0, 1, 15, 16, 127,
- 128, 255, 256, 1024, 2048, 4096, 2**16 -1, 2**16, 2**16 + 1, 2**30]
+ numbers = [ 2048, 4096, 2**16 -1, 2**16, 2**16 + 1, 2**30]
numbers.each do |n|
[n].pack('U').unpack('U').should == [n]
end
- [0x7F, 0x7F].pack('U*').should == "\x7F\x7F"
- [262193, 4736, 191, 12, 107].pack('U*').should == "\xF1\x80\x80\xB1\xE1\x8A\x80\xC2\xBF\x0C\x6B"
- lambda { [].pack('U') }.should raise_error(ArgumentError)
- lambda { [1].pack('UU') }.should raise_error(ArgumentError)
- lambda { [2**32].pack('U') }.should raise_error(RangeError)
- lambda { [-1].pack('U') }.should raise_error(RangeError)
- lambda { [-5].pack('U') }.should raise_error(RangeError)
- lambda { [-2**32].pack('U') }.should raise_error(RangeError)
end
end

0 comments on commit b239a3b

Please sign in to comment.
Something went wrong with that request. Please try again.