Commit 657ff554 authored by Nick Mathewson's avatar Nick Mathewson 🤹
Browse files

Split container.c based on container types, and minimize includes

Minimizing includes revealed other places includes were necessary.
parent b8be8265
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@
#define TOR_UTIL_BUG_H

#include "orconfig.h"
#include <stdlib.h>
#include "common/compat.h"
#include "lib/testsupport/testsupport.h"

+80 −0
Original line number Diff line number Diff line
/* Copyright (c) 2003-2004, Roger Dingledine
 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
 * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */

#ifndef TOR_BITARRAY_H
#define TOR_BITARRAY_H

#include "orconfig.h"
#include <string.h>
#include "lib/cc/torint.h"
#include "lib/malloc/util_malloc.h"

#if SIZEOF_INT == 4
#define BITARRAY_SHIFT 5
#elif SIZEOF_INT == 8
#define BITARRAY_SHIFT 6
#else
#error "int is neither 4 nor 8 bytes. I can't deal with that."
#endif /* SIZEOF_INT == 4 || ... */
#define BITARRAY_MASK ((1u<<BITARRAY_SHIFT)-1)

/** A random-access array of one-bit-wide elements. */
typedef unsigned int bitarray_t;
/** Create a new bit array that can hold <b>n_bits</b> bits. */
static inline bitarray_t *
bitarray_init_zero(unsigned int n_bits)
{
  /* round up to the next int. */
  size_t sz = (n_bits+BITARRAY_MASK) >> BITARRAY_SHIFT;
  return tor_calloc(sz, sizeof(unsigned int));
}
/** Expand <b>ba</b> from holding <b>n_bits_old</b> to <b>n_bits_new</b>,
 * clearing all new bits.  Returns a possibly changed pointer to the
 * bitarray. */
static inline bitarray_t *
bitarray_expand(bitarray_t *ba,
                unsigned int n_bits_old, unsigned int n_bits_new)
{
  size_t sz_old = (n_bits_old+BITARRAY_MASK) >> BITARRAY_SHIFT;
  size_t sz_new = (n_bits_new+BITARRAY_MASK) >> BITARRAY_SHIFT;
  char *ptr;
  if (sz_new <= sz_old)
    return ba;
  ptr = tor_reallocarray(ba, sz_new, sizeof(unsigned int));
  /* This memset does nothing to the older excess bytes.  But they were
   * already set to 0 by bitarry_init_zero. */
  memset(ptr+sz_old*sizeof(unsigned int), 0,
         (sz_new-sz_old)*sizeof(unsigned int));
  return (bitarray_t*) ptr;
}
/** Free the bit array <b>ba</b>. */
static inline void
bitarray_free_(bitarray_t *ba)
{
  tor_free(ba);
}
#define bitarray_free(ba) FREE_AND_NULL(bitarray_t, bitarray_free_, (ba))

/** Set the <b>bit</b>th bit in <b>b</b> to 1. */
static inline void
bitarray_set(bitarray_t *b, int bit)
{
  b[bit >> BITARRAY_SHIFT] |= (1u << (bit & BITARRAY_MASK));
}
/** Set the <b>bit</b>th bit in <b>b</b> to 0. */
static inline void
bitarray_clear(bitarray_t *b, int bit)
{
  b[bit >> BITARRAY_SHIFT] &= ~ (1u << (bit & BITARRAY_MASK));
}
/** Return true iff <b>bit</b>th bit in <b>b</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 /* !defined(TOR_CONTAINER_H) */
+49 −0
Original line number Diff line number Diff line
/* Copyright (c) 2003-2004, Roger Dingledine
 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
 * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */

/**
 * \file container.c
 * \brief Implements a smartlist (a resizable array) along
 * with helper functions to use smartlists.  Also includes
 * hash table implementations of a string-to-void* map, and of
 * a digest-to-void* map.
 **/

#include <stdlib.h>
#include "lib/malloc/util_malloc.h"
#include "lib/container/bloomfilt.h"
#include "common/util.h" // For tor_log2

/** Return a newly allocated digestset_t, optimized to hold a total of
 * <b>max_elements</b> digests with a reasonably low false positive weight. */
digestset_t *
digestset_new(int max_elements)
{
  /* The probability of false positives is about P=(1 - exp(-kn/m))^k, where k
   * is the number of hash functions per entry, m is the bits in the array,
   * and n is the number of elements inserted.  For us, k==4, n<=max_elements,
   * and m==n_bits= approximately max_elements*32.  This gives
   *   P<(1-exp(-4*n/(32*n)))^4 == (1-exp(1/-8))^4 == .00019
   *
   * It would be more optimal in space vs false positives to get this false
   * positive rate by going for k==13, and m==18.5n, but we also want to
   * conserve CPU, and k==13 is pretty big.
   */
  int n_bits = 1u << (tor_log2(max_elements)+5);
  digestset_t *r = tor_malloc(sizeof(digestset_t));
  r->mask = n_bits - 1;
  r->ba = bitarray_init_zero(n_bits);
  return r;
}

/** Free all storage held in <b>set</b>. */
void
digestset_free_(digestset_t *set)
{
  if (!set)
    return;
  bitarray_free(set->ba);
  tor_free(set);
}
+58 −0
Original line number Diff line number Diff line
/* Copyright (c) 2003-2004, Roger Dingledine
 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
 * Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */

#ifndef TOR_BLOOMFILT_H
#define TOR_BLOOMFILT_H

#include "orconfig.h"
#include "lib/cc/torint.h"
#include "lib/container/bitarray.h"
#include "siphash.h"

/** A set of digests, implemented as a Bloom filter. */
typedef struct {
  int mask; /**< One less than the number of bits in <b>ba</b>; always one less
             * than a power of two. */
  bitarray_t *ba; /**< A bit array to implement the Bloom filter. */
} digestset_t;

#define BIT(n) ((n) & set->mask)
/** Add the digest <b>digest</b> to <b>set</b>. */
static inline void
digestset_add(digestset_t *set, const char *digest)
{
  const uint64_t x = siphash24g(digest, 20);
  const uint32_t d1 = (uint32_t) x;
  const uint32_t d2 = (uint32_t)( (x>>16) + x);
  const uint32_t d3 = (uint32_t)( (x>>32) + x);
  const uint32_t d4 = (uint32_t)( (x>>48) + x);
  bitarray_set(set->ba, BIT(d1));
  bitarray_set(set->ba, BIT(d2));
  bitarray_set(set->ba, BIT(d3));
  bitarray_set(set->ba, BIT(d4));
}

/** If <b>digest</b> is in <b>set</b>, return nonzero.  Otherwise,
 * <em>probably</em> return zero. */
static inline int
digestset_contains(const digestset_t *set, const char *digest)
{
  const uint64_t x = siphash24g(digest, 20);
  const uint32_t d1 = (uint32_t) x;
  const uint32_t d2 = (uint32_t)( (x>>16) + x);
  const uint32_t d3 = (uint32_t)( (x>>32) + x);
  const uint32_t d4 = (uint32_t)( (x>>48) + x);
  return bitarray_is_set(set->ba, BIT(d1)) &&
         bitarray_is_set(set->ba, BIT(d2)) &&
         bitarray_is_set(set->ba, BIT(d3)) &&
         bitarray_is_set(set->ba, BIT(d4));
}
#undef BIT

digestset_t *digestset_new(int max_elements);
void digestset_free_(digestset_t* set);
#define digestset_free(set) FREE_AND_NULL(digestset_t, digestset_free_, (set))

#endif /* !defined(TOR_CONTAINER_H) */
+5 −740

File changed.

Preview size limit exceeded, changes collapsed.

Loading