diff --git a/lib/redis/commands/bitmaps.rb b/lib/redis/commands/bitmaps.rb index 720536a55..20240736f 100644 --- a/lib/redis/commands/bitmaps.rb +++ b/lib/redis/commands/bitmaps.rb @@ -27,9 +27,12 @@ def getbit(key, offset) # @param [String] key # @param [Integer] start start index # @param [Integer] stop stop index + # @param [Boolean] bytes_range whether the offset range is interpreted as a range of bits # @return [Integer] the number of bits set to 1 - def bitcount(key, start = 0, stop = -1) - send_command([:bitcount, key, start, stop]) + def bitcount(key, start = 0, stop = -1, bytes_range: true) + command = [:bitcount, key, start, stop] + command << 'BIT' unless bytes_range + send_command(command) end # Perform a bitwise operation between strings and store the resulting string in a key. @@ -51,14 +54,16 @@ def bitop(operation, destkey, *keys) # @param [Integer] bit whether to look for the first 1 or 0 bit # @param [Integer] start start index # @param [Integer] stop stop index + # @param [Boolean] bytes_range whether the offset range is interpreted as a range of bits # @return [Integer] the position of the first 1/0 bit. # -1 if looking for 1 and it is not found or start and stop are given. - def bitpos(key, bit, start = nil, stop = nil) + def bitpos(key, bit, start = nil, stop = nil, bytes_range: true) raise(ArgumentError, 'stop parameter specified without start parameter') if stop && !start command = [:bitpos, key, bit] command << start if start command << stop if stop + command << 'BIT' unless bytes_range send_command(command) end end diff --git a/lib/redis/distributed.rb b/lib/redis/distributed.rb index 249ecd3cc..556e741a7 100644 --- a/lib/redis/distributed.rb +++ b/lib/redis/distributed.rb @@ -370,8 +370,8 @@ def append(key, value) end # Count the number of set bits in a range of the string value stored at key. - def bitcount(key, start = 0, stop = -1) - node_for(key).bitcount(key, start, stop) + def bitcount(key, start = 0, stop = -1, bytes_range: true) + node_for(key).bitcount(key, start, stop, bytes_range: bytes_range) end # Perform a bitwise operation between strings and store the resulting string in a key. @@ -383,8 +383,8 @@ def bitop(operation, destkey, *keys) end # Return the position of the first bit set to 1 or 0 in a string. - def bitpos(key, bit, start = nil, stop = nil) - node_for(key).bitpos(key, bit, start, stop) + def bitpos(key, bit, start = nil, stop = nil, bytes_range: true) + node_for(key).bitpos(key, bit, start, stop, bytes_range: bytes_range) end # Set the string value of a key and return its old value. diff --git a/test/lint/strings.rb b/test/lint/strings.rb index 67fff6aa4..7e5fad041 100644 --- a/test/lint/strings.rb +++ b/test/lint/strings.rb @@ -249,6 +249,15 @@ def test_bitcount assert_equal 17, r.bitcount("foo", 0, -1) end + def test_bitcount_bits_range + target_version "7.0" do + r.set("foo", "abcde") + + assert_equal 10, r.bitcount("foo", 8, 31, bytes_range: false) + assert_equal 17, r.bitcount("foo", 0, -1, bytes_range: true) + end + end + def test_getrange r.set("foo", "abcde") diff --git a/test/redis/bitpos_test.rb b/test/redis/bitpos_test.rb index 0a62dfcae..90dadc068 100644 --- a/test/redis/bitpos_test.rb +++ b/test/redis/bitpos_test.rb @@ -41,6 +41,14 @@ def test_bitpos_one_intervals assert_equal(8, r.bitpos("foo", 1, 1, 1)) end + def test_bitpos_one_intervals_bit_range + target_version "7.0" do + r.set "foo", "\x00\xff\x00" + assert_equal(8, r.bitpos("foo", 1, 8, -1, bytes_range: false)) + assert_equal(-1, r.bitpos("foo", 1, 8, -1, bytes_range: true)) + end + end + def test_bitpos_raise_exception_if_stop_not_start assert_raises(ArgumentError) do r.bitpos("foo", 0, nil, 2)