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