bitarray.h 2.5 KB

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