diff --git a/src/main/java/io/lettuce/core/LettuceStrings.java b/src/main/java/io/lettuce/core/LettuceStrings.java index f0d7ce6902..a31a1fbfc5 100644 --- a/src/main/java/io/lettuce/core/LettuceStrings.java +++ b/src/main/java/io/lettuce/core/LettuceStrings.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2016 the original author or authors. + * Copyright 2011-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -60,7 +60,8 @@ public static boolean isNotEmpty(final CharSequence cs) { } /** - * Convert double to string. If double is infinite, returns positive/negative infinity {@code +inf} and {@code -inf}. + * Convert {@code double} to {@link String}. If {@code n} is infinite, returns positive/negative infinity {@code +inf} and + * {@code -inf}. * * @param n the double. * @return string representation of {@code n} @@ -72,6 +73,27 @@ public static String string(double n) { return Double.toString(n); } + /** + * Convert {@link String} to {@code double}. If {@code s} is {@literal +inf}/{@literal -inf}, returns positive/negative + * infinity. + * + * @param s string representation of the number + * @return the {@code double} value. + * @since 4.3.3 + */ + public static double toDouble(String s) { + + if ("+inf".equals(s) || "inf".equals(s)) { + return Double.POSITIVE_INFINITY; + } + + if ("-inf".equals(s)) { + return Double.NEGATIVE_INFINITY; + } + + return Double.parseDouble(s); + } + /** * Create SHA1 digest from Lua script. * diff --git a/src/main/java/io/lettuce/core/output/ScoredValueListOutput.java b/src/main/java/io/lettuce/core/output/ScoredValueListOutput.java index 6a79169eb5..478d956858 100644 --- a/src/main/java/io/lettuce/core/output/ScoredValueListOutput.java +++ b/src/main/java/io/lettuce/core/output/ScoredValueListOutput.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2016 the original author or authors. + * Copyright 2011-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,6 +19,7 @@ import java.util.ArrayList; import java.util.List; +import io.lettuce.core.LettuceStrings; import io.lettuce.core.ScoredValue; import io.lettuce.core.codec.RedisCodec; import io.lettuce.core.internal.LettuceAssert; @@ -30,8 +31,9 @@ * @param Value type. * @author Will Glozer */ -public class ScoredValueListOutput extends CommandOutput>> - implements StreamingOutput> { +public class ScoredValueListOutput extends CommandOutput>> implements + StreamingOutput> { + private V value; private Subscriber> subscriber; @@ -47,7 +49,7 @@ public void set(ByteBuffer bytes) { return; } - double score = Double.parseDouble(decodeAscii(bytes)); + double score = LettuceStrings.toDouble(decodeAscii(bytes)); subscriber.onNext(ScoredValue.fromNullable(score, value)); value = null; } diff --git a/src/main/java/io/lettuce/core/output/ScoredValueScanOutput.java b/src/main/java/io/lettuce/core/output/ScoredValueScanOutput.java index 8a2fc35713..73bdd218fc 100644 --- a/src/main/java/io/lettuce/core/output/ScoredValueScanOutput.java +++ b/src/main/java/io/lettuce/core/output/ScoredValueScanOutput.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2016 the original author or authors. + * Copyright 2011-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,6 +17,7 @@ import java.nio.ByteBuffer; +import io.lettuce.core.LettuceStrings; import io.lettuce.core.ScoredValue; import io.lettuce.core.ScoredValueScanCursor; import io.lettuce.core.codec.RedisCodec; @@ -44,7 +45,7 @@ protected void setOutput(ByteBuffer bytes) { return; } - double score = Double.parseDouble(decodeAscii(bytes)); + double score = LettuceStrings.toDouble(decodeAscii(bytes)); output.getValues().add(ScoredValue.fromNullable(score, value)); value = null; } diff --git a/src/main/java/io/lettuce/core/output/ScoredValueScanStreamingOutput.java b/src/main/java/io/lettuce/core/output/ScoredValueScanStreamingOutput.java index a923e72797..5015578ae3 100644 --- a/src/main/java/io/lettuce/core/output/ScoredValueScanStreamingOutput.java +++ b/src/main/java/io/lettuce/core/output/ScoredValueScanStreamingOutput.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2016 the original author or authors. + * Copyright 2011-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,6 +17,7 @@ import java.nio.ByteBuffer; +import io.lettuce.core.LettuceStrings; import io.lettuce.core.ScoredValue; import io.lettuce.core.StreamScanCursor; import io.lettuce.core.codec.RedisCodec; @@ -45,7 +46,7 @@ protected void setOutput(ByteBuffer bytes) { return; } - double score = Double.parseDouble(decodeAscii(bytes)); + double score = LettuceStrings.toDouble(decodeAscii(bytes)); channel.onValue(ScoredValue.fromNullable(score, value)); value = null; output.setCount(output.getCount() + 1); diff --git a/src/main/java/io/lettuce/core/output/ScoredValueStreamingOutput.java b/src/main/java/io/lettuce/core/output/ScoredValueStreamingOutput.java index debda979ca..e431d61d4b 100644 --- a/src/main/java/io/lettuce/core/output/ScoredValueStreamingOutput.java +++ b/src/main/java/io/lettuce/core/output/ScoredValueStreamingOutput.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2016 the original author or authors. + * Copyright 2011-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,6 +17,7 @@ import java.nio.ByteBuffer; +import io.lettuce.core.LettuceStrings; import io.lettuce.core.ScoredValue; import io.lettuce.core.codec.RedisCodec; @@ -44,7 +45,7 @@ public void set(ByteBuffer bytes) { return; } - double score = Double.parseDouble(decodeAscii(bytes)); + double score = LettuceStrings.toDouble(decodeAscii(bytes)); channel.onValue(ScoredValue.fromNullable(score, value)); value = null; output = output.longValue() + 1; diff --git a/src/test/java/io/lettuce/core/commands/SortedSetCommandTest.java b/src/test/java/io/lettuce/core/commands/SortedSetCommandTest.java index 55eeef5949..ceae0f08ca 100644 --- a/src/test/java/io/lettuce/core/commands/SortedSetCommandTest.java +++ b/src/test/java/io/lettuce/core/commands/SortedSetCommandTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2016 the original author or authors. + * Copyright 2011-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,6 +15,7 @@ */ package io.lettuce.core.commands; +import static io.lettuce.core.Range.Boundary.including; import static io.lettuce.core.ZStoreArgs.Builder.max; import static io.lettuce.core.ZStoreArgs.Builder.min; import static io.lettuce.core.ZStoreArgs.Builder.sum; @@ -146,7 +147,7 @@ public void zcount() throws Exception { assertThat(redis.zcount(key, Range.create(1.0, 2.0))).isEqualTo(2); assertThat(redis.zcount(key, Range.create(NEGATIVE_INFINITY, POSITIVE_INFINITY))).isEqualTo(3); - assertThat(redis.zcount(key, Range.from(Boundary.excluding(1.0), Boundary.including(3.0)))).isEqualTo(2); + assertThat(redis.zcount(key, Range.from(Boundary.excluding(1.0), including(3.0)))).isEqualTo(2); assertThat(redis.zcount(key, Range.unbounded())).isEqualTo(3); } @@ -219,7 +220,8 @@ public void zrangebyscore() throws Exception { assertThat(redis.zrangebyscore(key, "-inf", "+inf", 2, 2)).isEqualTo(list("c", "d")); assertThat(redis.zrangebyscore(key, Range.create(2.0, 3.0))).isEqualTo(list("b", "c")); - assertThat(redis.zrangebyscore(key, Range.from(Boundary.excluding(1.0), Boundary.excluding(4.0)))).isEqualTo(list("b", "c")); + assertThat(redis.zrangebyscore(key, Range.from(Boundary.excluding(1.0), Boundary.excluding(4.0)))).isEqualTo( + list("b", "c")); assertThat(redis.zrangebyscore(key, Range.unbounded())).isEqualTo(list("a", "b", "c", "d")); assertThat(redis.zrangebyscore(key, Range.create(0.0, 4.0), Limit.create(1, 3))).isEqualTo(list("b", "c", "d")); assertThat(redis.zrangebyscore(key, Range.unbounded(), Limit.create(2, 2))).isEqualTo(list("c", "d")); @@ -239,7 +241,8 @@ public void zrangebyscoreStreaming() throws Exception { assertThat(redis.zrangebyscore(streamingAdapter, key, "-inf", "+inf", 2, 2)).isEqualTo(2); assertThat(redis.zrangebyscore(streamingAdapter, key, Range.create(2.0, 3.0))).isEqualTo(2); - assertThat(redis.zrangebyscore(streamingAdapter, key, Range.from(Boundary.excluding(1.0), Boundary.excluding(4.0)))).isEqualTo(2); + assertThat(redis.zrangebyscore(streamingAdapter, key, Range.from(Boundary.excluding(1.0), Boundary.excluding(4.0)))) + .isEqualTo(2); assertThat(redis.zrangebyscore(streamingAdapter, key, Range.unbounded())).isEqualTo(4); assertThat(redis.zrangebyscore(streamingAdapter, key, Range.create(0.0, 4.0), Limit.create(1, 3))).isEqualTo(3); assertThat(redis.zrangebyscore(streamingAdapter, key, Range.unbounded(), Limit.create(2, 2))).isEqualTo(2); @@ -262,12 +265,30 @@ public void zrangebyscoreWithScores() throws Exception { assertThat(redis.zrangebyscoreWithScores(key, "-inf", "+inf", 2, 2)).isEqualTo(svlist(sv(3.0, "c"), sv(4.0, "d"))); assertThat(redis.zrangebyscoreWithScores(key, Range.create(2.0, 3.0))).isEqualTo(svlist(sv(2.0, "b"), sv(3.0, "c"))); - assertThat(redis.zrangebyscoreWithScores(key, Range.from(Boundary.excluding(1.0), Boundary.excluding(4.0)))).isEqualTo(svlist(sv(2.0, "b"), sv(3.0, "c"))); + assertThat(redis.zrangebyscoreWithScores(key, Range.from(Boundary.excluding(1.0), Boundary.excluding(4.0)))).isEqualTo( + svlist(sv(2.0, "b"), sv(3.0, "c"))); assertThat(redis.zrangebyscoreWithScores(key, Range.unbounded())).isEqualTo( svlist(sv(1.0, "a"), sv(2.0, "b"), sv(3.0, "c"), sv(4.0, "d"))); assertThat(redis.zrangebyscoreWithScores(key, Range.create(0.0, 4.0), Limit.create(1, 3))).isEqualTo( svlist(sv(2.0, "b"), sv(3.0, "c"), sv(4.0, "d"))); - assertThat(redis.zrangebyscoreWithScores(key, Range.unbounded(), Limit.create(2, 2))).isEqualTo(svlist(sv(3.0, "c"), sv(4.0, "d"))); + assertThat(redis.zrangebyscoreWithScores(key, Range.unbounded(), Limit.create(2, 2))).isEqualTo( + svlist(sv(3.0, "c"), sv(4.0, "d"))); + } + + @Test + @SuppressWarnings({ "unchecked" }) + public void zrangebyscoreWithScoresInfinity() throws Exception { + + redis.zadd(key, Double.POSITIVE_INFINITY, "a", Double.NEGATIVE_INFINITY, "b"); + + assertThat(redis.zrangebyscoreWithScores(key, "-inf", "+inf")).hasSize(2); + + ListStreamingAdapter streamingAdapter = new ListStreamingAdapter<>(); + + Range range = Range.from(including(Double.NEGATIVE_INFINITY), including(Double.POSITIVE_INFINITY)); + redis.zrangebyscoreWithScores(streamingAdapter, key, range); + + assertThat(streamingAdapter.getList()).hasSize(2); } @Test @@ -284,11 +305,14 @@ public void zrangebyscoreWithScoresStreaming() throws Exception { assertThat(redis.zrangebyscoreWithScores(streamingAdapter, key, 0.0, 4.0, 1, 3).longValue()).isEqualTo(3); assertThat(redis.zrangebyscoreWithScores(streamingAdapter, key, "-inf", "+inf", 2, 2).longValue()).isEqualTo(2); - assertThat(redis.zrangebyscoreWithScores(streamingAdapter,key, Range.create(2.0, 3.0))).isEqualTo(2); - assertThat(redis.zrangebyscoreWithScores(streamingAdapter,key, Range.from(Boundary.excluding(1.0), Boundary.excluding(4.0)))).isEqualTo(2); - assertThat(redis.zrangebyscoreWithScores(streamingAdapter,key, Range.unbounded())).isEqualTo(4); - assertThat(redis.zrangebyscoreWithScores(streamingAdapter,key, Range.create(0.0, 4.0), Limit.create(1, 3))).isEqualTo(3); - assertThat(redis.zrangebyscoreWithScores(streamingAdapter,key, Range.unbounded(), Limit.create(2, 2))).isEqualTo(2); + assertThat(redis.zrangebyscoreWithScores(streamingAdapter, key, Range.create(2.0, 3.0))).isEqualTo(2); + assertThat( + redis.zrangebyscoreWithScores(streamingAdapter, key, + Range.from(Boundary.excluding(1.0), Boundary.excluding(4.0)))).isEqualTo(2); + assertThat(redis.zrangebyscoreWithScores(streamingAdapter, key, Range.unbounded())).isEqualTo(4); + assertThat(redis.zrangebyscoreWithScores(streamingAdapter, key, Range.create(0.0, 4.0), Limit.create(1, 3))).isEqualTo( + 3); + assertThat(redis.zrangebyscoreWithScores(streamingAdapter, key, Range.unbounded(), Limit.create(2, 2))).isEqualTo(2); } @@ -380,8 +404,9 @@ public void zrevrangebylex() throws Exception { assertThat(redis.zrevrangebylex(key, Range.unbounded())).hasSize(100); assertThat(redis.zrevrangebylex(key, Range.create("value", "zzz"))).hasSize(100); - assertThat(redis.zrevrangebylex(key, Range.from(Boundary.including("value98"), Boundary.including("value99")))).containsSequence("value99", "value98"); - assertThat(redis.zrevrangebylex(key, Range.from(Boundary.including("value99"), Boundary.unbounded()))).hasSize(1); + assertThat(redis.zrevrangebylex(key, Range.from(including("value98"), including("value99")))).containsSequence( + "value99", "value98"); + assertThat(redis.zrevrangebylex(key, Range.from(including("value99"), Boundary.unbounded()))).hasSize(1); assertThat(redis.zrevrangebylex(key, Range.from(Boundary.excluding("value99"), Boundary.unbounded()))).hasSize(0); } @@ -398,7 +423,8 @@ public void zrevrangebyscore() throws Exception { assertThat(redis.zrevrangebyscore(key, "+inf", "-inf", 2, 2)).isEqualTo(list("b", "a")); assertThat(redis.zrevrangebyscore(key, Range.create(2.0, 3.0))).isEqualTo(list("c", "b")); - assertThat(redis.zrevrangebyscore(key, Range.from(Boundary.excluding(1.0), Boundary.excluding(4.0)))).isEqualTo(list("c", "b")); + assertThat(redis.zrevrangebyscore(key, Range.from(Boundary.excluding(1.0), Boundary.excluding(4.0)))).isEqualTo( + list("c", "b")); assertThat(redis.zrevrangebyscore(key, Range.unbounded())).isEqualTo(list("d", "c", "b", "a")); assertThat(redis.zrevrangebyscore(key, Range.create(0.0, 4.0), Limit.create(1, 3))).isEqualTo(list("c", "b", "a")); assertThat(redis.zrevrangebyscore(key, Range.unbounded(), Limit.create(2, 2))).isEqualTo(list("b", "a")); @@ -420,12 +446,14 @@ public void zrevrangebyscoreWithScores() throws Exception { assertThat(redis.zrevrangebyscoreWithScores(key, "+inf", "-inf", 2, 2)).isEqualTo(svlist(sv(2.0, "b"), sv(1.0, "a"))); assertThat(redis.zrevrangebyscoreWithScores(key, Range.create(2.0, 3.0))).isEqualTo(svlist(sv(3.0, "c"), sv(2.0, "b"))); - assertThat(redis.zrevrangebyscoreWithScores(key, Range.from(Boundary.excluding(1.0), Boundary.excluding(4.0)))).isEqualTo(svlist(sv(3.0, "c"), sv(2.0, "b"))); + assertThat(redis.zrevrangebyscoreWithScores(key, Range.from(Boundary.excluding(1.0), Boundary.excluding(4.0)))) + .isEqualTo(svlist(sv(3.0, "c"), sv(2.0, "b"))); assertThat(redis.zrevrangebyscoreWithScores(key, Range.unbounded())).isEqualTo( svlist(sv(4.0, "d"), sv(3.0, "c"), sv(2.0, "b"), sv(1.0, "a"))); assertThat(redis.zrevrangebyscoreWithScores(key, Range.create(0.0, 4.0), Limit.create(1, 3))).isEqualTo( svlist(sv(3.0, "c"), sv(2.0, "b"), sv(1.0, "a"))); - assertThat(redis.zrevrangebyscoreWithScores(key, Range.unbounded(), Limit.create(2, 2))).isEqualTo(svlist(sv(2.0, "b"), sv(1.0, "a"))); + assertThat(redis.zrevrangebyscoreWithScores(key, Range.unbounded(), Limit.create(2, 2))).isEqualTo( + svlist(sv(2.0, "b"), sv(1.0, "a"))); } @Test @@ -442,10 +470,14 @@ public void zrevrangebyscoreStreaming() throws Exception { assertThat(redis.zrevrangebyscore(streamingAdapter, key, "+inf", "-inf", 2, 2).longValue()).isEqualTo(2); assertThat(redis.zrevrangebyscore(streamingAdapter, key, Range.create(2.0, 3.0)).longValue()).isEqualTo(2); - assertThat(redis.zrevrangebyscore(streamingAdapter, key, Range.from(Boundary.excluding(1.0), Boundary.excluding(4.0))).longValue()).isEqualTo(2); + assertThat( + redis.zrevrangebyscore(streamingAdapter, key, Range.from(Boundary.excluding(1.0), Boundary.excluding(4.0))) + .longValue()).isEqualTo(2); assertThat(redis.zrevrangebyscore(streamingAdapter, key, Range.unbounded()).longValue()).isEqualTo(4); - assertThat(redis.zrevrangebyscore(streamingAdapter, key, Range.create(0.0, 4.0), Limit.create(1, 3)).longValue()).isEqualTo(3); - assertThat(redis.zrevrangebyscore(streamingAdapter, key, Range.unbounded(), Limit.create(2, 2)).longValue()).isEqualTo(2); + assertThat(redis.zrevrangebyscore(streamingAdapter, key, Range.create(0.0, 4.0), Limit.create(1, 3)).longValue()) + .isEqualTo(3); + assertThat(redis.zrevrangebyscore(streamingAdapter, key, Range.unbounded(), Limit.create(2, 2)).longValue()).isEqualTo( + 2); } @Test @@ -463,10 +495,15 @@ public void zrevrangebyscoreWithScoresStreaming() throws Exception { assertThat(redis.zrevrangebyscoreWithScores(streamingAdapter, key, "+inf", "-inf", 2, 2)).isEqualTo(2); assertThat(redis.zrevrangebyscoreWithScores(streamingAdapter, key, Range.create(2.0, 3.0)).longValue()).isEqualTo(2); - assertThat(redis.zrevrangebyscoreWithScores(streamingAdapter, key, Range.from(Boundary.excluding(1.0), Boundary.excluding(4.0))).longValue()).isEqualTo(2); + assertThat( + redis.zrevrangebyscoreWithScores(streamingAdapter, key, + Range.from(Boundary.excluding(1.0), Boundary.excluding(4.0))).longValue()).isEqualTo(2); assertThat(redis.zrevrangebyscoreWithScores(streamingAdapter, key, Range.unbounded()).longValue()).isEqualTo(4); - assertThat(redis.zrevrangebyscoreWithScores(streamingAdapter, key, Range.create(0.0, 4.0), Limit.create(1, 3)).longValue()).isEqualTo(3); - assertThat(redis.zrevrangebyscoreWithScores(streamingAdapter, key, Range.unbounded(), Limit.create(2, 2)).longValue()).isEqualTo(2); + assertThat( + redis.zrevrangebyscoreWithScores(streamingAdapter, key, Range.create(0.0, 4.0), Limit.create(1, 3)).longValue()) + .isEqualTo(3); + assertThat(redis.zrevrangebyscoreWithScores(streamingAdapter, key, Range.unbounded(), Limit.create(2, 2)).longValue()) + .isEqualTo(2); } @Test @@ -656,7 +693,7 @@ public void zlexcount() throws Exception { assertThat(redis.zlexcount(key, Range.unbounded())).isEqualTo(100); assertThat(redis.zlexcount(key, Range.create("value", "zzz"))).isEqualTo(100); - assertThat(redis.zlexcount(key, Range.from(Boundary.including("value99"), Boundary.unbounded()))).isEqualTo(1); + assertThat(redis.zlexcount(key, Range.from(including("value99"), Boundary.unbounded()))).isEqualTo(1); assertThat(redis.zlexcount(key, Range.from(Boundary.excluding("value99"), Boundary.unbounded()))).isEqualTo(0); } @@ -669,8 +706,9 @@ public void zrangebylex() throws Exception { assertThat(redis.zrangebylex(key, Range.unbounded())).hasSize(100); assertThat(redis.zrangebylex(key, Range.create("value", "zzz"))).hasSize(100); - assertThat(redis.zrangebylex(key, Range.from(Boundary.including("value98"), Boundary.including("value99")))).containsSequence("value98", "value99"); - assertThat(redis.zrangebylex(key, Range.from(Boundary.including("value99"), Boundary.unbounded()))).hasSize(1); + assertThat(redis.zrangebylex(key, Range.from(including("value98"), including("value99")))).containsSequence("value98", + "value99"); + assertThat(redis.zrangebylex(key, Range.from(including("value99"), Boundary.unbounded()))).hasSize(1); assertThat(redis.zrangebylex(key, Range.from(Boundary.excluding("value99"), Boundary.unbounded()))).hasSize(0); }