bitarray.h 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. /* Copyright (c) 2003-2004, Roger Dingledine
  2. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
  3. * Copyright (c) 2007-2018, The Tor Project, Inc. */
  4. /* See LICENSE for licensing information */
  5. #ifndef TOR_BITARRAY_H
  6. #define TOR_BITARRAY_H
  7. /**
  8. * \file bitarray.h
  9. *
  10. * \brief Implements a variable-sized (but non-resizeable) bit-array.
  11. **/
  12. #include "orconfig.h"
  13. #include <string.h>
  14. #include "lib/cc/torint.h"
  15. #include "lib/malloc/util_malloc.h"
  16. #if SIZEOF_INT == 4
  17. #define BITARRAY_SHIFT 5
  18. #elif SIZEOF_INT == 8
  19. #define BITARRAY_SHIFT 6
  20. #else
  21. #error "int is neither 4 nor 8 bytes. I can't deal with that."
  22. #endif /* SIZEOF_INT == 4 || ... */
  23. #define BITARRAY_MASK ((1u<<BITARRAY_SHIFT)-1)
  24. /** A random-access array of one-bit-wide elements. */
  25. typedef unsigned int bitarray_t;
  26. /** Create a new bit array that can hold <b>n_bits</b> bits. */
  27. static inline bitarray_t *
  28. bitarray_init_zero(unsigned int n_bits)
  29. {
  30. /* round up to the next int. */
  31. size_t sz = (n_bits+BITARRAY_MASK) >> BITARRAY_SHIFT;
  32. return tor_calloc(sz, sizeof(unsigned int));
  33. }
  34. /** Expand <b>ba</b> from holding <b>n_bits_old</b> to <b>n_bits_new</b>,
  35. * clearing all new bits. Returns a possibly changed pointer to the
  36. * bitarray. */
  37. static inline bitarray_t *
  38. bitarray_expand(bitarray_t *ba,
  39. unsigned int n_bits_old, unsigned int n_bits_new)
  40. {
  41. size_t sz_old = (n_bits_old+BITARRAY_MASK) >> BITARRAY_SHIFT;
  42. size_t sz_new = (n_bits_new+BITARRAY_MASK) >> BITARRAY_SHIFT;
  43. char *ptr;
  44. if (sz_new <= sz_old)
  45. return ba;
  46. ptr = tor_reallocarray(ba, sz_new, sizeof(unsigned int));
  47. /* This memset does nothing to the older excess bytes. But they were
  48. * already set to 0 by bitarry_init_zero. */
  49. memset(ptr+sz_old*sizeof(unsigned int), 0,
  50. (sz_new-sz_old)*sizeof(unsigned int));
  51. return (bitarray_t*) ptr;
  52. }
  53. /** Free the bit array <b>ba</b>. */
  54. static inline void
  55. bitarray_free_(bitarray_t *ba)
  56. {
  57. tor_free(ba);
  58. }
  59. #define bitarray_free(ba) FREE_AND_NULL(bitarray_t, bitarray_free_, (ba))
  60. /** Set the <b>bit</b>th bit in <b>b</b> to 1. */
  61. static inline void
  62. bitarray_set(bitarray_t *b, int bit)
  63. {
  64. b[bit >> BITARRAY_SHIFT] |= (1u << (bit & BITARRAY_MASK));
  65. }
  66. /** Set the <b>bit</b>th bit in <b>b</b> to 0. */
  67. static inline void
  68. bitarray_clear(bitarray_t *b, int bit)
  69. {
  70. b[bit >> BITARRAY_SHIFT] &= ~ (1u << (bit & BITARRAY_MASK));
  71. }
  72. /** Return true iff <b>bit</b>th bit in <b>b</b> is nonzero. NOTE: does
  73. * not necessarily return 1 on true. */
  74. static inline unsigned int
  75. bitarray_is_set(bitarray_t *b, int bit)
  76. {
  77. return b[bit >> BITARRAY_SHIFT] & (1u << (bit & BITARRAY_MASK));
  78. }
  79. #endif /* !defined(TOR_CONTAINER_H) */