This is an automated email from the ASF dual-hosted git repository.

jt2594838 pushed a commit to branch add_bitmap_interface
in repository https://gitbox.apache.org/repos/asf/tsfile.git

commit 3dacbaa4552f8bf028e6bbe3227bb090f891788f
Author: Tian Jiang <[email protected]>
AuthorDate: Thu Jul 30 16:48:18 2026 +0800

    add range test interface
---
 .../main/java/org/apache/tsfile/utils/BitMap.java  | 29 ++++++++++++++++
 .../java/org/apache/tsfile/utils/BitMapImpl.java   | 35 +++++++++++++++++++
 .../java/org/apache/tsfile/utils/BitMapTest.java   | 40 ++++++++++++++++++++++
 3 files changed, 104 insertions(+)

diff --git a/java/common/src/main/java/org/apache/tsfile/utils/BitMap.java 
b/java/common/src/main/java/org/apache/tsfile/utils/BitMap.java
index 629cda9c0..337bec90f 100644
--- a/java/common/src/main/java/org/apache/tsfile/utils/BitMap.java
+++ b/java/common/src/main/java/org/apache/tsfile/utils/BitMap.java
@@ -54,6 +54,35 @@ public class BitMap implements Accountable {
     return implementation.isMarked(position);
   }
 
+  /**
+   * Returns whether at least one bit in the specified range is marked. An 
empty range returns
+   * {@code false}.
+   *
+   * @throws IndexOutOfBoundsException if the range is outside this bitmap
+   */
+  public boolean isRangeAnyMarked(int start, int length) {
+    return implementation.isRangeAnyMarked(start, length);
+  }
+
+  /**
+   * Returns whether every bit in the specified range is marked. An empty 
range returns {@code
+   * true}.
+   *
+   * @throws IndexOutOfBoundsException if the range is outside this bitmap
+   */
+  public boolean isRangeAllMarked(int start, int length) {
+    return implementation.isRangeAllMarked(start, length);
+  }
+
+  /**
+   * Returns whether no bit in the specified range is marked. An empty range 
returns {@code true}.
+   *
+   * @throws IndexOutOfBoundsException if the range is outside this bitmap
+   */
+  public boolean isRangeNoneMarked(int start, int length) {
+    return implementation.isRangeNoneMarked(start, length);
+  }
+
   /** mark as 1 at all positions. */
   public void markAll() {
     implementation.markAll();
diff --git a/java/common/src/main/java/org/apache/tsfile/utils/BitMapImpl.java 
b/java/common/src/main/java/org/apache/tsfile/utils/BitMapImpl.java
index d9f296fe2..801e67cc8 100644
--- a/java/common/src/main/java/org/apache/tsfile/utils/BitMapImpl.java
+++ b/java/common/src/main/java/org/apache/tsfile/utils/BitMapImpl.java
@@ -19,6 +19,8 @@
 
 package org.apache.tsfile.utils;
 
+import org.apache.tsfile.i18n.Messages;
+
 abstract class BitMapImpl {
 
   protected int size;
@@ -39,6 +41,32 @@ abstract class BitMapImpl {
 
   abstract boolean isMarked(int position);
 
+  boolean isRangeAnyMarked(int start, int length) {
+    checkRange(start, length);
+    for (int offset = 0; offset < length; offset += Long.SIZE) {
+      int batchSize = Math.min(length - offset, Long.SIZE);
+      if (extractBits(start + offset, batchSize) != 0L) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  boolean isRangeAllMarked(int start, int length) {
+    checkRange(start, length);
+    for (int offset = 0; offset < length; offset += Long.SIZE) {
+      int batchSize = Math.min(length - offset, Long.SIZE);
+      if (extractBits(start + offset, batchSize) != 
BitMapLongImpl.lowerBitsMask(batchSize)) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  boolean isRangeNoneMarked(int start, int length) {
+    return !isRangeAnyMarked(start, length);
+  }
+
   abstract void markAll();
 
   abstract void mark(int position);
@@ -102,4 +130,11 @@ abstract class BitMapImpl {
   abstract BitMapImpl extend(int newSize);
 
   abstract long getRetainedSizeInBytes();
+
+  private void checkRange(int start, int length) {
+    if (start < 0 || length < 0 || start > size - length) {
+      throw new IndexOutOfBoundsException(
+          Messages.format("error.common.bitmap_start_length_out_of_range", 
start, length, size));
+    }
+  }
 }
diff --git a/java/tsfile/src/test/java/org/apache/tsfile/utils/BitMapTest.java 
b/java/tsfile/src/test/java/org/apache/tsfile/utils/BitMapTest.java
index e4b59e452..ef73614ad 100644
--- a/java/tsfile/src/test/java/org/apache/tsfile/utils/BitMapTest.java
+++ b/java/tsfile/src/test/java/org/apache/tsfile/utils/BitMapTest.java
@@ -27,6 +27,7 @@ import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertThrows;
 import static org.junit.Assert.assertTrue;
 
 public class BitMapTest {
@@ -217,6 +218,45 @@ public class BitMapTest {
     assertFalse(bitMap.isAllUnmarked(10));
   }
 
+  @Test
+  public void testRangeMarkedQueries() {
+    assertRangeMarkedQueries(new BitMap(0));
+    assertRangeMarkedQueries(new BitMap(64));
+    assertRangeMarkedQueries(BitMap.createBitMapDynamically(64));
+    assertRangeMarkedQueries(new BitMap(100));
+  }
+
+  private void assertRangeMarkedQueries(BitMap bitMap) {
+    for (int i = 0; i < bitMap.getSize(); i++) {
+      if (i % 4 != 2) {
+        bitMap.mark(i);
+      }
+    }
+
+    for (int start = 0; start <= bitMap.getSize(); start++) {
+      for (int length = 0; length <= bitMap.getSize() - start; length++) {
+        boolean anyMarked = false;
+        boolean allMarked = true;
+        for (int i = start; i < start + length; i++) {
+          anyMarked |= bitMap.isMarked(i);
+          allMarked &= bitMap.isMarked(i);
+        }
+        assertEquals(anyMarked, bitMap.isRangeAnyMarked(start, length));
+        assertEquals(allMarked, bitMap.isRangeAllMarked(start, length));
+        assertEquals(!anyMarked, bitMap.isRangeNoneMarked(start, length));
+      }
+    }
+
+    assertThrows(IndexOutOfBoundsException.class, () -> 
bitMap.isRangeAnyMarked(-1, 0));
+    assertThrows(IndexOutOfBoundsException.class, () -> 
bitMap.isRangeAllMarked(0, -1));
+    assertThrows(
+        IndexOutOfBoundsException.class, () -> 
bitMap.isRangeNoneMarked(bitMap.getSize() + 1, 0));
+    assertThrows(
+        IndexOutOfBoundsException.class, () -> 
bitMap.isRangeAnyMarked(bitMap.getSize(), 1));
+    assertThrows(
+        IndexOutOfBoundsException.class, () -> bitMap.isRangeAllMarked(1, 
Integer.MAX_VALUE));
+  }
+
   @Test
   public void testGetTruncatedByteArray() {
     BitMap bitMap = new BitMap(16);

Reply via email to