diff --git a/src/common/container.h b/src/common/container.h
index db5967208a..a342b26670 100644
--- a/src/common/container.h
+++ b/src/common/container.h
@@ -267,5 +267,49 @@ void* strmap_remove_lc(strmap_t *map, const char *key);
return digestmap_iter_done((digestmap_iter_t*)iter); \
}
+#if SIZEOF_INT == 4
+#define BITARRAY_SHIFT 5
+#define BITARRAY_MASK 31
+#elif SIZEOF_INT == 8
+#define BITARRAY_SHIFT 6
+#define BITARRAY_MASK 63
+#else
+#error "int is neither 4 nor 8 bites. I can't deal with that."
+#endif
+
+typedef unsigned int bitarray_t;
+/** Create a new bit array that can hold n_bits bits. */
+static INLINE bitarray_t *
+bitarray_init_zero(int n_bits)
+{
+ size_t sz = (n_bits+BITARRAY_MASK) & BITARRAY_MASK;
+ return tor_malloc_zero(sz*sizeof(unsigned int));
+}
+/** Free the bit array ba. */
+static INLINE void
+bitarray_free(bitarray_t *ba)
+{
+ tor_free(ba);
+}
+/** Set the bitth bit in b to 1. */
+static INLINE void
+bitarray_set(bitarray_t *b, int bit)
+{
+ b[bit >> BITARRAY_SHIFT] |= (1u << (bit & BITARRAY_MASK));
+}
+/** Set the bitth bit in b to 0. */
+static INLINE void
+bitarray_clear(bitarray_t *b, int bit)
+{
+ b[bit >> BITARRAY_SHIFT] &= ~ (1u << (bit & BITARRAY_MASK));
+}
+/** Return true iff bitth bit in b is nonzero. NOTE: does
+ * not necessarily return 1 on true. */
+static INLINE unsigned int
+bitarray_is_set(bitarray_t *b, int bit)
+{
+ return b[bit >> BITARRAY_SHIFT] & (1u << (bit & BITARRAY_MASK));
+}
+
#endif
diff --git a/src/or/test.c b/src/or/test.c
index 2776fcbfc1..147023a8de 100644
--- a/src/or/test.c
+++ b/src/or/test.c
@@ -1544,6 +1544,43 @@ test_smartlist(void)
smartlist_free(sl);
}
+static void
+test_bitarray(void)
+{
+ bitarray_t *ba;
+ int i, j, ok=1;
+
+ ba = bitarray_init_zero(1);
+ test_assert(! bitarray_is_set(ba, 0));
+ bitarray_set(ba, 0);
+ test_assert(bitarray_is_set(ba, 0));
+ bitarray_clear(ba, 0);
+ test_assert(! bitarray_is_set(ba, 0));
+ bitarray_free(ba);
+
+ ba = bitarray_init_zero(1023);
+ for (i = 1; i < 64; ) {
+ for (j = 0; j < 1023; ++j) {
+ if (j % i)
+ bitarray_set(ba, j);
+ else
+ bitarray_clear(ba, j);
+ }
+ for (j = 0; j < 1023; ++j) {
+ if (!bool_eq(bitarray_is_set(ba, j), j%i))
+ ok = 0;
+ }
+ test_assert(ok);
+ if (i < 7)
+ ++i;
+ else if (i == 28)
+ i = 32;
+ else
+ i += 7;
+ }
+ bitarray_free(ba);
+}
+
/* stop threads running at once. */
static tor_mutex_t *_thread_test_mutex = NULL;
/* make sure that threads have to run at the same time. */
@@ -2990,6 +3027,8 @@ main(int c, char**v)
test_util();
puts("\n--smartlist");
test_smartlist();
+ puts("\n--bitarray");
+ test_bitarray();
puts("\n--mempool");
test_mempool();
puts("\n--strmap");