r12980@Kushana: nickm | 2007-05-18 14:11:05 -0400

Add a "swap" function to smartlist, add a "shuffle" function for smartlist to crypto.c, and make appropriate hashtable functions be more const.


svn:r10208
This commit is contained in:
Nick Mathewson 2007-05-18 21:19:14 +00:00
parent 43d64df4fc
commit a187704872
5 changed files with 49 additions and 22 deletions

View File

@ -658,28 +658,28 @@ DEFINE_MAP_STRUCTS(digestmap_t, char key[DIGEST_LEN], digestmap_);
/** Helper: compare strmap_entry_t objects by key value. */ /** Helper: compare strmap_entry_t objects by key value. */
static INLINE int static INLINE int
strmap_entries_eq(strmap_entry_t *a, strmap_entry_t *b) strmap_entries_eq(const strmap_entry_t *a, const strmap_entry_t *b)
{ {
return !strcmp(a->key, b->key); return !strcmp(a->key, b->key);
} }
/** Helper: return a hash value for a strmap_entry_t. */ /** Helper: return a hash value for a strmap_entry_t. */
static INLINE unsigned int static INLINE unsigned int
strmap_entry_hash(strmap_entry_t *a) strmap_entry_hash(const strmap_entry_t *a)
{ {
return ht_string_hash(a->key); return ht_string_hash(a->key);
} }
/** Helper: compare digestmap_entry_t objects by key value. */ /** Helper: compare digestmap_entry_t objects by key value. */
static INLINE int static INLINE int
digestmap_entries_eq(digestmap_entry_t *a, digestmap_entry_t *b) digestmap_entries_eq(const digestmap_entry_t *a, const digestmap_entry_t *b)
{ {
return !memcmp(a->key, b->key, DIGEST_LEN); return !memcmp(a->key, b->key, DIGEST_LEN);
} }
/** Helper: return a hash value for a digest_map_t. */ /** Helper: return a hash value for a digest_map_t. */
static INLINE unsigned int static INLINE unsigned int
digestmap_entry_hash(digestmap_entry_t *a) digestmap_entry_hash(const digestmap_entry_t *a)
{ {
uint32_t *p = (uint32_t*)a->key; uint32_t *p = (uint32_t*)a->key;
return ht_improve_hash(p[0] ^ p[1] ^ p[2] ^ p[3] ^ p[4]); return ht_improve_hash(p[0] ^ p[1] ^ p[2] ^ p[3] ^ p[4]);
@ -780,7 +780,7 @@ digestmap_set(digestmap_t *map, const char *key, void *val)
* value is set. * value is set.
*/ */
void * void *
strmap_get(strmap_t *map, const char *key) strmap_get(const strmap_t *map, const char *key)
{ {
strmap_entry_t *resolve; strmap_entry_t *resolve;
strmap_entry_t search; strmap_entry_t search;
@ -797,7 +797,7 @@ strmap_get(strmap_t *map, const char *key)
/** Like strmap_get() above but for digestmaps. */ /** Like strmap_get() above but for digestmaps. */
void * void *
digestmap_get(digestmap_t *map, const char *key) digestmap_get(const digestmap_t *map, const char *key)
{ {
digestmap_entry_t *resolve; digestmap_entry_t *resolve;
digestmap_entry_t search; digestmap_entry_t search;
@ -874,7 +874,7 @@ strmap_set_lc(strmap_t *map, const char *key, void *val)
/** Same as strmap_get, but first converts <b>key</b> to lowercase. */ /** Same as strmap_get, but first converts <b>key</b> to lowercase. */
void * void *
strmap_get_lc(strmap_t *map, const char *key) strmap_get_lc(const strmap_t *map, const char *key)
{ {
void *v; void *v;
char *lc_key = tor_strdup(key); char *lc_key = tor_strdup(key);
@ -1058,38 +1058,38 @@ digestmap_free(digestmap_t *map, void (*free_val)(void*))
} }
void void
strmap_assert_ok(strmap_t *map) strmap_assert_ok(const strmap_t *map)
{ {
tor_assert(!_strmap_impl_HT_REP_IS_BAD(&map->head)); tor_assert(!_strmap_impl_HT_REP_IS_BAD(&map->head));
} }
void void
digestmap_assert_ok(digestmap_t *map) digestmap_assert_ok(const digestmap_t *map)
{ {
tor_assert(!_digestmap_impl_HT_REP_IS_BAD(&map->head)); tor_assert(!_digestmap_impl_HT_REP_IS_BAD(&map->head));
} }
/** Return true iff <b>map</b> has no entries. */ /** Return true iff <b>map</b> has no entries. */
int int
strmap_isempty(strmap_t *map) strmap_isempty(const strmap_t *map)
{ {
return HT_EMPTY(&map->head); return HT_EMPTY(&map->head);
} }
int int
digestmap_isempty(digestmap_t *map) digestmap_isempty(const digestmap_t *map)
{ {
return HT_EMPTY(&map->head); return HT_EMPTY(&map->head);
} }
/** Return the number of items in <b>map</b>. */ /** Return the number of items in <b>map</b>. */
int int
strmap_size(strmap_t *map) strmap_size(const strmap_t *map)
{ {
return HT_SIZE(&map->head); return HT_SIZE(&map->head);
} }
int int
digestmap_size(digestmap_t *map) digestmap_size(const digestmap_t *map)
{ {
return HT_SIZE(&map->head); return HT_SIZE(&map->head);
} }

View File

@ -78,6 +78,17 @@ extern INLINE void smartlist_set(smartlist_t *sl, int idx, void *val) {
#define smartlist_set(sl, idx, val) ((sl)->list[idx] = (val)) #define smartlist_set(sl, idx, val) ((sl)->list[idx] = (val))
#endif #endif
void smartlist_swap(smartlist_t *sl, int idx1, int idx2);
/**DOCDOC*/
extern INLINE void smartlist_swap(smartlist_t *sl, int idx1, int idx2)
{
if (idx1 != idx2) {
void *elt = smartlist_get(sl, idx1);
smartlist_set(sl, idx1, smartlist_get(sl, idx2));
smartlist_set(sl, idx2, elt);
}
}
void smartlist_del(smartlist_t *sl, int idx); void smartlist_del(smartlist_t *sl, int idx);
void smartlist_del_keeporder(smartlist_t *sl, int idx); void smartlist_del_keeporder(smartlist_t *sl, int idx);
void smartlist_insert(smartlist_t *sl, int idx, void *val); void smartlist_insert(smartlist_t *sl, int idx, void *val);
@ -171,24 +182,24 @@ char *smartlist_join_strings2(smartlist_t *sl, const char *join,
typedef struct prefix##entry_t *prefix##iter_t; \ typedef struct prefix##entry_t *prefix##iter_t; \
maptype* prefix##new(void); \ maptype* prefix##new(void); \
void* prefix##set(maptype *map, keytype key, void *val); \ void* prefix##set(maptype *map, keytype key, void *val); \
void* prefix##get(maptype *map, keytype key); \ void* prefix##get(const maptype *map, keytype key); \
void* prefix##remove(maptype *map, keytype key); \ void* prefix##remove(maptype *map, keytype key); \
void prefix##free(maptype *map, void (*free_val)(void*)); \ void prefix##free(maptype *map, void (*free_val)(void*)); \
int prefix##isempty(maptype *map); \ int prefix##isempty(const maptype *map); \
int prefix##size(maptype *map); \ int prefix##size(const maptype *map); \
prefix##iter_t *prefix##iter_init(maptype *map); \ prefix##iter_t *prefix##iter_init(maptype *map); \
prefix##iter_t *prefix##iter_next(maptype *map, prefix##iter_t *iter); \ prefix##iter_t *prefix##iter_next(maptype *map, prefix##iter_t *iter); \
prefix##iter_t *prefix##iter_next_rmv(maptype *map, prefix##iter_t *iter); \ prefix##iter_t *prefix##iter_next_rmv(maptype *map, prefix##iter_t *iter); \
void prefix##iter_get(prefix##iter_t *iter, keytype *keyp, void **valp); \ void prefix##iter_get(prefix##iter_t *iter, keytype *keyp, void **valp); \
int prefix##iter_done(prefix##iter_t *iter); \ int prefix##iter_done(prefix##iter_t *iter); \
void prefix##assert_ok(maptype *map); void prefix##assert_ok(const maptype *map);
/* Map from const char * to void *. Implemented with a hash table. */ /* Map from const char * to void *. Implemented with a hash table. */
DECLARE_MAP_FNS(strmap_t, const char *, strmap_); DECLARE_MAP_FNS(strmap_t, const char *, strmap_);
DECLARE_MAP_FNS(digestmap_t, const char *, digestmap_); DECLARE_MAP_FNS(digestmap_t, const char *, digestmap_);
void* strmap_set_lc(strmap_t *map, const char *key, void *val); void* strmap_set_lc(strmap_t *map, const char *key, void *val);
void* strmap_get_lc(strmap_t *map, const char *key); void* strmap_get_lc(const strmap_t *map, const char *key);
void* strmap_remove_lc(strmap_t *map, const char *key); void* strmap_remove_lc(strmap_t *map, const char *key);
#endif #endif

View File

@ -1677,6 +1677,21 @@ smartlist_choose(const smartlist_t *sl)
return NULL; /* no elements to choose from */ return NULL; /* no elements to choose from */
} }
/** Scramble the elements of sl into a random order. */
void
smartlist_shuffle(smartlist_t *sl)
{
int i;
/* From the end of the list to the front, choose at random from the
positions we haven't looked at yet, and swap that position into the
current position. Remember to give "no swap" the same probability as
any other swap. */
for (i = smartlist_len(sl)-1; i > 0; --i) {
int j = crypto_rand_int(i+1);
smartlist_swap(sl, i, j);
}
}
/** Base-64 encode <b>srclen</b> bytes of data from <b>src</b>. Write /** Base-64 encode <b>srclen</b> bytes of data from <b>src</b>. Write
* the result into <b>dest</b>, if it will fit within <b>destlen</b> * the result into <b>dest</b>, if it will fit within <b>destlen</b>
* bytes. Return the number of bytes written on success; -1 if * bytes. Return the number of bytes written on success; -1 if

View File

@ -157,6 +157,7 @@ uint64_t crypto_rand_uint64(uint64_t max);
struct smartlist_t; struct smartlist_t;
void *smartlist_choose(const struct smartlist_t *sl); void *smartlist_choose(const struct smartlist_t *sl);
void smartlist_shuffle(struct smartlist_t *sl);
int base64_encode(char *dest, size_t destlen, const char *src, size_t srclen); int base64_encode(char *dest, size_t destlen, const char *src, size_t srclen);
int base64_decode(char *dest, size_t destlen, const char *src, size_t srclen); int base64_decode(char *dest, size_t destlen, const char *src, size_t srclen);

View File

@ -91,7 +91,7 @@ ht_string_hash(const char *s)
#define HT_PROTOTYPE(name, type, field, hashfn, eqfn) \ #define HT_PROTOTYPE(name, type, field, hashfn, eqfn) \
int name##_HT_GROW(struct name *ht, unsigned min_capacity); \ int name##_HT_GROW(struct name *ht, unsigned min_capacity); \
void name##_HT_CLEAR(struct name *ht); \ void name##_HT_CLEAR(struct name *ht); \
int _##name##_HT_REP_IS_BAD(struct name *ht); \ int _##name##_HT_REP_IS_BAD(const struct name *ht); \
static INLINE void \ static INLINE void \
name##_HT_INIT(struct name *head) { \ name##_HT_INIT(struct name *head) { \
head->hth_table_length = 0; \ head->hth_table_length = 0; \
@ -119,11 +119,11 @@ ht_string_hash(const char *s)
/* Return a pointer to the element in the table 'head' matching 'elm', \ /* Return a pointer to the element in the table 'head' matching 'elm', \
* or NULL if no such element exists */ \ * or NULL if no such element exists */ \
static INLINE struct type * \ static INLINE struct type * \
name##_HT_FIND(struct name *head, struct type *elm) \ name##_HT_FIND(const struct name *head, struct type *elm) \
{ \ { \
struct type **p; \ struct type **p; \
_HT_SET_HASH(elm, field, hashfn); \ _HT_SET_HASH(elm, field, hashfn); \
p = _##name##_HT_FIND_P(head, elm); \ p = _##name##_HT_FIND_P((struct name *)head, elm); \
return p ? *p : NULL; \ return p ? *p : NULL; \
} \ } \
/* Insert the element 'elm' into the table 'head'. Do not call this \ /* Insert the element 'elm' into the table 'head'. Do not call this \
@ -349,7 +349,7 @@ ht_string_hash(const char *s)
/* Debugging helper: return false iff the representation of 'head' is \ /* Debugging helper: return false iff the representation of 'head' is \
* internally consistent. */ \ * internally consistent. */ \
int \ int \
_##name##_HT_REP_IS_BAD(struct name *head) \ _##name##_HT_REP_IS_BAD(const struct name *head) \
{ \ { \
unsigned n, i; \ unsigned n, i; \
struct type *elm; \ struct type *elm; \