lib/bindata/int.rb in bindata-2.1.0 vs lib/bindata/int.rb in bindata-2.2.0
- old
+ new
@@ -63,110 +63,110 @@
"val = (val < #{min}) ? #{min} : (val > #{max}) ? #{max} : val"
end
def create_read_code(nbits, endian, signed)
- unpack_str = create_read_unpack_code(nbits, endian, signed)
- assemble_str = create_read_assemble_code(nbits, endian, signed)
+ read_str = create_raw_read_code(nbits, endian, signed)
- read_str = "(#{unpack_str} ; #{assemble_str})"
-
- if need_conversion_code?(nbits, signed)
+ if need_signed_conversion_code?(nbits, signed)
"val = #{read_str} ; #{create_uint2int_code(nbits)}"
else
read_str
end
end
+ def create_raw_read_code(nbits, endian, signed)
+ # special case 8bit integers for speed
+ if nbits == 8
+ "io.readbytes(1).ord"
+ else
+ unpack_str = create_read_unpack_code(nbits, endian, signed)
+ assemble_str = create_read_assemble_code(nbits, endian, signed)
+
+ "(#{unpack_str} ; #{assemble_str})"
+ end
+ end
+
def create_read_unpack_code(nbits, endian, signed)
- nbytes = nbits / 8
+ nbytes = nbits / 8
+ pack_directive = pack_directive(nbits, endian, signed)
- "ints = io.readbytes(#{nbytes}).unpack('#{pack_directive(nbits, endian, signed)}')"
+ "ints = io.readbytes(#{nbytes}).unpack('#{pack_directive}')"
end
def create_read_assemble_code(nbits, endian, signed)
- bits_per_word = bytes_per_word(nbits) * 8
- nwords = nbits / bits_per_word
+ nwords = nbits / bits_per_word(nbits)
idx = (0 ... nwords).to_a
idx.reverse! if (endian == :big)
parts = (0 ... nwords).collect do |i|
- if i.zero?
- "ints.at(#{idx[i]})"
- else
- "(ints.at(#{idx[i]}) << #{bits_per_word * i})"
- end
+ "(ints.at(#{idx[i]}) << #{bits_per_word(nbits) * i})"
end
+ parts[0].sub!(/ << 0\b/, "") # Remove " << 0" for optimisation
assemble_str = parts.join(" + ")
end
def create_to_binary_s_code(nbits, endian, signed)
# special case 8bit integers for speed
return "(val & 0xff).chr" if nbits == 8
- bits_per_word = bytes_per_word(nbits) * 8
- nwords = nbits / bits_per_word
- mask = (1 << bits_per_word) - 1
+ pack_directive = pack_directive(nbits, endian, signed)
+ words = val_as_packed_words(nbits, endian, signed)
+ pack_str = "[#{words}].pack('#{pack_directive}')"
- vals = (0 ... nwords).collect do |i|
- i.zero? ? "val" : "val >> #{bits_per_word * i}"
- end
- vals.reverse! if (endian == :big)
-
- array_str = "[" + vals.collect { |val| "#{val} & #{mask}" }.join(", ") + "]" # TODO: "& mask" is needed to work around jruby bug
- pack_str = "#{array_str}.pack('#{pack_directive(nbits, endian, signed)}')"
-
- if need_conversion_code?(nbits, signed)
+ if need_signed_conversion_code?(nbits, signed)
"#{create_int2uint_code(nbits)} ; #{pack_str}"
else
pack_str
end
end
+ def val_as_packed_words(nbits, endian, signed)
+ nwords = nbits / bits_per_word(nbits)
+ mask = (1 << bits_per_word(nbits)) - 1
+
+ vals = (0 ... nwords).collect { |i| "val >> #{bits_per_word(nbits) * i}" }
+ vals[0].sub!(/ >> 0\b/, "") # Remove " >> 0" for optimisation
+ vals.reverse! if (endian == :big)
+
+ vals = vals.collect { |val| "#{val} & #{mask}" } # TODO: "& mask" is needed to work around jruby bug. Remove this line when fixed.
+ vals.join(",")
+ end
+
def create_int2uint_code(nbits)
"val &= #{(1 << nbits) - 1}"
end
def create_uint2int_code(nbits)
"(val >= #{1 << (nbits - 1)}) ? val - #{1 << nbits} : val"
end
- def bytes_per_word(nbits)
- (nbits % 64).zero? ? 8 :
- (nbits % 32).zero? ? 4 :
- (nbits % 16).zero? ? 2 :
- 1
+ def bits_per_word(nbits)
+ (nbits % 64).zero? ? 64 :
+ (nbits % 32).zero? ? 32 :
+ (nbits % 16).zero? ? 16 :
+ 8
end
def pack_directive(nbits, endian, signed)
- bits_per_word = bytes_per_word(nbits) * 8
- nwords = nbits / bits_per_word
+ nwords = nbits / bits_per_word(nbits)
- if (nbits % 64).zero?
- d = (endian == :big) ? 'Q>' : 'Q<'
- elsif (nbits % 32).zero?
- d = (endian == :big) ? 'L>' : 'L<'
- elsif (nbits % 16).zero?
- d = (endian == :big) ? 'S>' : 'S<'
- else
- d = 'C'
- end
+ directives = { 8 => "C", 16 => "S", 32 => "L", 64 => "Q" }
- if pack_directive_signed?(nbits, signed)
+ d = directives[bits_per_word(nbits)]
+ d << ((endian == :big) ? ">" : "<") unless d == "C"
+
+ if signed == :signed and directives.has_key?(nbits)
(d * nwords).downcase
else
d * nwords
end
end
- def need_conversion_code?(nbits, signed)
- signed == :signed and not pack_directive_signed?(nbits, signed)
- end
-
- def pack_directive_signed?(nbits, signed)
- signed == :signed and [64, 32, 16, 8].include?(nbits)
+ def need_signed_conversion_code?(nbits, signed)
+ signed == :signed and not [64, 32, 16].include?(nbits)
end
end
end