Merge commit '1fa53c5bf8d0717f784c79abaa5111f88ab00221'

This commit is contained in:
Toni Uhlig
2021-09-15 17:04:21 +02:00
34 changed files with 377 additions and 272 deletions

View File

@@ -7,7 +7,7 @@ matrix:
compiler: clang
- os: osx
script:
- make -C tests EXTRA_CFLAGS="-W -Wall -Wextra"
- make -C tests EXTRA_CFLAGS="-W -Wall -Wextra -Wswitch-default"
- make -C tests clean ; make -C tests pedantic
- make -C tests clean ; make -C tests pedantic EXTRA_CFLAGS=-DNO_DECLTYPE
- make -C tests clean ; make -C tests cplusplus

View File

@@ -1,4 +1,4 @@
Copyright (c) 2005-2018, Troy D. Hanson http://troydhanson.github.com/uthash/
Copyright (c) 2005-2021, Troy D. Hanson http://troydhanson.github.io/uthash/
All rights reserved.
Redistribution and use in source and binary forms, with or without

View File

@@ -1,8 +1,8 @@
[![Build status](https://travis-ci.org/Quuxplusone/uthash.svg?branch=travis-ci)](https://travis-ci.org/troydhanson/uthash)
[![Build status](https://api.travis-ci.org/troydhanson/uthash.svg?branch=master)](https://travis-ci.org/troydhanson/uthash)
Documentation for uthash is available at:
http://troydhanson.github.com/uthash/
https://troydhanson.github.io/uthash/

View File

@@ -5,6 +5,21 @@ Click to return to the link:index.html[uthash home page].
NOTE: This ChangeLog may be incomplete and/or incorrect. See the git commit log.
Version 2.3.0 (2021-02-25)
--------------------------
* remove HASH_FCN; the HASH_FUNCTION and HASH_KEYCMP macros now behave similarly
* remove uthash_memcmp (deprecated in v2.1.0) in favor of HASH_KEYCMP
* silence -Wswitch-default warnings (thanks, Olaf Bergmann!)
Version 2.2.0 (2020-12-17)
--------------------------
* add HASH_NO_STDINT for platforms without C99 <stdint.h>
* silence many -Wcast-qual warnings (thanks, Olaf Bergmann!)
* skip hash computation when finding in an empty hash (thanks, Huansong Fu!)
* rename oom to utarray_oom, in utarray.h (thanks, Hong Xu!)
* rename oom to utstring_oom, in utstring.h (thanks, Hong Xu!)
* remove MurmurHash/HASH_MUR
Version 2.1.0 (2018-12-20)
--------------------------
* silence some Clang static analysis warnings
@@ -56,7 +71,7 @@ Version 1.9.8 (2013-03-10)
* `HASH_REPLACE` now in uthash (thanks, Nick Vatamaniuc!)
* fixed clang warnings (thanks wynnw!)
* fixed `utarray_insert` when inserting past array end (thanks Rob Willett!)
* you can now find http://troydhanson.github.com/uthash/[uthash on GitHub]
* you can now find http://troydhanson.github.io/uthash/[uthash on GitHub]
* there's a https://groups.google.com/d/forum/uthash[uthash Google Group]
* uthash has been downloaded 29,000+ times since 2006 on SourceForge

View File

@@ -14,7 +14,7 @@
<div id="topnav">
<a href="http://github.com/troydhanson/uthash">GitHub page</a> &gt;
uthash home <!-- http://troydhanson.github.com/uthash/ -->
uthash home <!-- http://troydhanson.github.io/uthash/ -->
<a href="https://twitter.com/share" class="twitter-share-button" data-via="troydhanson">Tweet</a>
<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>

View File

@@ -13,7 +13,7 @@
</div> <!-- banner -->
<div id="topnav">
<a href="http://troydhanson.github.com/uthash/">uthash home</a> &gt;
<a href="http://troydhanson.github.io/uthash/">uthash home</a> &gt;
BSD license
</div>
@@ -21,7 +21,7 @@
<div id="mid">
<div id="main">
<pre>
Copyright (c) 2005-2018, Troy D. Hanson http://troydhanson.github.com/uthash/
Copyright (c) 2005-2021, Troy D. Hanson http://troydhanson.github.io/uthash/
All rights reserved.
Redistribution and use in source and binary forms, with or without

View File

@@ -1,7 +1,7 @@
uthash User Guide
=================
Troy D. Hanson, Arthur O'Dwyer
v2.1.0, December 2018
v2.3.0, February 2021
To download uthash, follow this link back to the
https://github.com/troydhanson/uthash[GitHub project page].
@@ -215,7 +215,7 @@ a unique value. Then call `HASH_ADD`. (Here we use the convenience macro
void add_user(int user_id, char *name) {
struct my_struct *s;
s = malloc(sizeof(struct my_struct));
s = malloc(sizeof *s);
s->id = user_id;
strcpy(s->name, name);
HASH_ADD_INT(users, id, s); /* id: name of key field */
@@ -227,7 +227,7 @@ second parameter is the 'name' of the key field. Here, this is `id`. The
last parameter is a pointer to the structure being added.
[[validc]]
.Wait.. the field name is a parameter?
.Wait.. the parameter is a field name?
*******************************************************************************
If you find it strange that `id`, which is the 'name of a field' in the
structure, can be passed as a parameter... welcome to the world of macros. Don't
@@ -403,7 +403,7 @@ num_users = HASH_COUNT(users);
printf("there are %u users\n", num_users);
----------------------------------------------------------------------
Incidentally, this works even the list (`users`, here) is `NULL`, in
Incidentally, this works even if the list head (here, `users`) is `NULL`, in
which case the count is 0.
Iterating and sorting
@@ -430,7 +430,7 @@ the hash, starting from any known item.
Deletion-safe iteration
^^^^^^^^^^^^^^^^^^^^^^^
In the example above, it would not be safe to delete and free `s` in the body
of the 'for' loop, (because `s` is derefenced each time the loop iterates).
of the 'for' loop, (because `s` is dereferenced each time the loop iterates).
This is easy to rewrite correctly (by copying the `s->hh.next` pointer to a
temporary variable 'before' freeing `s`), but it comes up often enough that a
deletion-safe iteration macro, `HASH_ITER`, is included. It expands to a
@@ -452,7 +452,7 @@ doubly-linked list.
*******************************************************************************
If you're using uthash in a C++ program, you need an extra cast on the `for`
iterator, e.g., `s=(struct my_struct*)s->hh.next`.
iterator, e.g., `s = static_cast<my_struct*>(s->hh.next)`.
Sorting
^^^^^^^
@@ -479,20 +479,20 @@ Below, `name_sort` and `id_sort` are two examples of sort functions.
.Sorting the items in the hash
----------------------------------------------------------------------
int name_sort(struct my_struct *a, struct my_struct *b) {
int by_name(const struct my_struct *a, const struct my_struct *b) {
return strcmp(a->name, b->name);
}
int id_sort(struct my_struct *a, struct my_struct *b) {
int by_id(const struct my_struct *a, const struct my_struct *b) {
return (a->id - b->id);
}
void sort_by_name() {
HASH_SORT(users, name_sort);
HASH_SORT(users, by_name);
}
void sort_by_id() {
HASH_SORT(users, id_sort);
HASH_SORT(users, by_id);
}
----------------------------------------------------------------------
@@ -516,45 +516,50 @@ Follow the prompts to try the program.
.A complete program
----------------------------------------------------------------------
#include <stdio.h> /* gets */
#include <stdio.h> /* printf */
#include <stdlib.h> /* atoi, malloc */
#include <string.h> /* strcpy */
#include "uthash.h"
struct my_struct {
int id; /* key */
char name[10];
char name[21];
UT_hash_handle hh; /* makes this structure hashable */
};
struct my_struct *users = NULL;
void add_user(int user_id, char *name) {
void add_user(int user_id, const char *name)
{
struct my_struct *s;
HASH_FIND_INT(users, &user_id, s); /* id already in the hash? */
if (s == NULL) {
s = (struct my_struct*)malloc(sizeof *s);
s->id = user_id;
HASH_ADD_INT( users, id, s ); /* id: name of key field */
HASH_ADD_INT(users, id, s); /* id is the key field */
}
strcpy(s->name, name);
}
struct my_struct *find_user(int user_id) {
struct my_struct *find_user(int user_id)
{
struct my_struct *s;
HASH_FIND_INT(users, &user_id, s); /* s: output pointer */
return s;
}
void delete_user(struct my_struct *user) {
void delete_user(struct my_struct *user)
{
HASH_DEL(users, user); /* user: pointer to deletee */
free(user);
}
void delete_all() {
struct my_struct *current_user, *tmp;
void delete_all()
{
struct my_struct *current_user;
struct my_struct *tmp;
HASH_ITER(hh, users, current_user, tmp) {
HASH_DEL(users, current_user); /* delete it (users advances to next) */
@@ -562,7 +567,8 @@ void delete_all() {
}
}
void print_users() {
void print_users()
{
struct my_struct *s;
for (s = users; s != NULL; s = (struct my_struct*)(s->hh.next)) {
@@ -570,31 +576,40 @@ void print_users() {
}
}
int name_sort(struct my_struct *a, struct my_struct *b) {
int by_name(const struct my_struct *a, const struct my_struct *b)
{
return strcmp(a->name, b->name);
}
int id_sort(struct my_struct *a, struct my_struct *b) {
int by_id(const struct my_struct *a, const struct my_struct *b)
{
return (a->id - b->id);
}
void sort_by_name() {
HASH_SORT(users, name_sort);
const char *getl(const char *prompt)
{
static char buf[21];
char *p;
printf("%s? ", prompt); fflush(stdout);
p = fgets(buf, sizeof(buf), stdin);
if (p == NULL || (p = strchr(buf, '\n')) == NULL) {
puts("Invalid input!");
exit(EXIT_FAILURE);
}
*p = '\0';
return buf;
}
void sort_by_id() {
HASH_SORT(users, id_sort);
}
int main(int argc, char *argv[]) {
char in[10];
int id=1, running=1;
int main()
{
int id = 1;
int running = 1;
struct my_struct *s;
unsigned num_users;
int temp;
while (running) {
printf(" 1. add user\n");
printf(" 2. add/rename user by id\n");
printf(" 2. add or rename user by id\n");
printf(" 3. find user\n");
printf(" 4. delete user\n");
printf(" 5. delete all users\n");
@@ -603,44 +618,41 @@ int main(int argc, char *argv[]) {
printf(" 8. print users\n");
printf(" 9. count users\n");
printf("10. quit\n");
gets(in);
switch(atoi(in)) {
switch (atoi(getl("Command"))) {
case 1:
printf("name?\n");
add_user(id++, gets(in));
add_user(id++, getl("Name (20 char max)"));
break;
case 2:
printf("id?\n");
gets(in); id = atoi(in);
printf("name?\n");
add_user(id, gets(in));
temp = atoi(getl("ID"));
add_user(temp, getl("Name (20 char max)"));
break;
case 3:
printf("id?\n");
s = find_user(atoi(gets(in)));
s = find_user(atoi(getl("ID to find")));
printf("user: %s\n", s ? s->name : "unknown");
break;
case 4:
printf("id?\n");
s = find_user(atoi(gets(in)));
if (s) delete_user(s);
else printf("id unknown\n");
s = find_user(atoi(getl("ID to delete")));
if (s) {
delete_user(s);
} else {
printf("id unknown\n");
}
break;
case 5:
delete_all();
break;
case 6:
sort_by_name();
HASH_SORT(users, by_name);
break;
case 7:
sort_by_id();
HASH_SORT(users, by_id);
break;
case 8:
print_users();
break;
case 9:
num_users=HASH_COUNT(users);
printf("there are %u users\n", num_users);
temp = HASH_COUNT(users);
printf("there are %d users\n", temp);
break;
case 10:
running = 0;
@@ -1119,7 +1131,7 @@ always used with the `users_by_name` hash table).
int i;
char *name;
s = malloc(sizeof(struct my_struct));
s = malloc(sizeof *s);
s->id = 1;
strcpy(s->username, "thanson");
@@ -1240,7 +1252,8 @@ for a structure to be usable with `HASH_SELECT`, it must have two or more hash
handles. (As described <<multihash,here>>, a structure can exist in many
hash tables at the same time; it must have a separate hash handle for each one).
user_t *users=NULL, *admins=NULL; /* two hash tables */
user_t *users = NULL; /* hash table of users */
user_t *admins = NULL; /* hash table of admins */
typedef struct {
int id;
@@ -1256,21 +1269,22 @@ users who have id's less than 1024.
The first two parameters are the 'destination' hash handle and hash table, the
second two parameters are the 'source' hash handle and hash table, and the last
parameter is the 'select condition'. Here we used a macro `is_admin()` but we
parameter is the 'select condition'. Here we used a macro `is_admin(x)` but we
could just as well have used a function.
int is_admin(void *userv) {
user_t *user = (user_t*)userv;
int is_admin(const void *userv) {
user_t *user = (const user_t*)userv;
return (user->id < 1024) ? 1 : 0;
}
If the select condition always evaluates to true, this operation is
essentially a 'merge' of the source hash into the destination hash. Of course,
the source hash remains unchanged under any use of `HASH_SELECT`. It only adds
items to the destination hash selectively.
essentially a 'merge' of the source hash into the destination hash.
The two hash handles must differ. An example of using `HASH_SELECT` is included
in `tests/test36.c`.
`HASH_SELECT` adds items to the destination without removing them from
the source; the source hash table remains unchanged. The destination hash table
must not be the same as the source hash table.
An example of using `HASH_SELECT` is included in `tests/test36.c`.
[[hash_keycompare]]
Specifying an alternate key comparison function
@@ -1795,7 +1809,7 @@ In order to use the convenience macros,
|===============================================================================
|macro | arguments
|HASH_ADD_INT | (head, keyfield_name, item_ptr)
|HASH_REPLACE_INT | (head, keyfiled_name, item_ptr,replaced_item_ptr)
|HASH_REPLACE_INT | (head, keyfield_name, item_ptr, replaced_item_ptr)
|HASH_FIND_INT | (head, key_ptr, item_ptr)
|HASH_ADD_STR | (head, keyfield_name, item_ptr)
|HASH_REPLACE_STR | (head, keyfield_name, item_ptr, replaced_item_ptr)

View File

@@ -1,7 +1,7 @@
utarray: dynamic array macros for C
===================================
Troy D. Hanson <tdh@tkhanson.net>
v2.1.0, December 2018
v2.3.0, February 2021
Here's a link back to the https://github.com/troydhanson/uthash[GitHub project page].

View File

@@ -1,7 +1,7 @@
utlist: linked list macros for C structures
===========================================
Troy D. Hanson <tdh@tkhanson.net>
v2.1.0, December 2018
v2.3.0, February 2021
Here's a link back to the https://github.com/troydhanson/uthash[GitHub project page].

View File

@@ -1,7 +1,7 @@
utringbuffer: dynamic ring-buffer macros for C
==============================================
Arthur O'Dwyer <arthur.j.odwyer@gmail.com>
v2.1.0, December 2018
v2.3.0, February 2021
Here's a link back to the https://github.com/troydhanson/uthash[GitHub project page].

View File

@@ -1,7 +1,7 @@
utstack: intrusive stack macros for C
=====================================
Arthur O'Dwyer <arthur.j.odwyer@gmail.com>
v2.1.0, December 2018
v2.3.0, February 2021
Here's a link back to the https://github.com/troydhanson/uthash[GitHub project page].

View File

@@ -1,7 +1,7 @@
utstring: dynamic string macros for C
=====================================
Troy D. Hanson <tdh@tkhanson.net>
v2.1.0, December 2018
v2.3.0, February 2021
Here's a link back to the https://github.com/troydhanson/uthash[GitHub project page].

View File

@@ -24,5 +24,5 @@
"src/utstring.h"
],
"version": "2.1.0"
"version": "2.3.0"
}

View File

@@ -1,5 +1,5 @@
/*
Copyright (c) 2008-2018, Troy D. Hanson http://troydhanson.github.com/uthash/
Copyright (c) 2008-2021, Troy D. Hanson http://troydhanson.github.io/uthash/
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -26,7 +26,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef UTARRAY_H
#define UTARRAY_H
#define UTARRAY_VERSION 2.1.0
#define UTARRAY_VERSION 2.3.0
#include <stddef.h> /* size_t */
#include <string.h> /* memset, etc */
@@ -232,8 +232,9 @@ typedef struct {
/* last we pre-define a few icd for common utarrays of ints and strings */
static void utarray_str_cpy(void *dst, const void *src) {
char **_src = (char**)src, **_dst = (char**)dst;
*_dst = (*_src == NULL) ? NULL : strdup(*_src);
char *const *srcc = (char *const *)src;
char **dstc = (char**)dst;
*dstc = (*srcc == NULL) ? NULL : strdup(*srcc);
}
static void utarray_str_dtor(void *elt) {
char **eltc = (char**)elt;

View File

@@ -1,5 +1,5 @@
/*
Copyright (c) 2003-2018, Troy D. Hanson http://troydhanson.github.com/uthash/
Copyright (c) 2003-2021, Troy D. Hanson http://troydhanson.github.io/uthash/
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -24,12 +24,22 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef UTHASH_H
#define UTHASH_H
#define UTHASH_VERSION 2.1.0
#define UTHASH_VERSION 2.3.0
#include <string.h> /* memcmp, memset, strlen */
#include <stddef.h> /* ptrdiff_t */
#include <stdlib.h> /* exit */
#if defined(HASH_DEFINE_OWN_STDINT) && HASH_DEFINE_OWN_STDINT
/* This codepath is provided for backward compatibility, but I plan to remove it. */
#warning "HASH_DEFINE_OWN_STDINT is deprecated; please use HASH_NO_STDINT instead"
typedef unsigned int uint32_t;
typedef unsigned char uint8_t;
#elif defined(HASH_NO_STDINT) && HASH_NO_STDINT
#else
#include <stdint.h> /* uint8_t, uint32_t */
#endif
/* These macros use decltype or the earlier __typeof GNU extension.
As decltype is only available in newer compilers (VS2010 or gcc 4.3+
when compiling c++ source) this code uses whatever method is needed
@@ -62,23 +72,6 @@ do {
} while (0)
#endif
/* a number of the hash function use uint32_t which isn't defined on Pre VS2010 */
#if defined(_WIN32)
#if defined(_MSC_VER) && _MSC_VER >= 1600
#include <stdint.h>
#elif defined(__WATCOMC__) || defined(__MINGW32__) || defined(__CYGWIN__)
#include <stdint.h>
#else
typedef unsigned int uint32_t;
typedef unsigned char uint8_t;
#endif
#elif defined(__GNUC__) && !defined(__VXWORKS__)
#include <stdint.h>
#else
typedef unsigned int uint32_t;
typedef unsigned char uint8_t;
#endif
#ifndef uthash_malloc
#define uthash_malloc(sz) malloc(sz) /* malloc fcn */
#endif
@@ -92,15 +85,12 @@ typedef unsigned char uint8_t;
#define uthash_strlen(s) strlen(s)
#endif
#ifdef uthash_memcmp
/* This warning will not catch programs that define uthash_memcmp AFTER including uthash.h. */
#warning "uthash_memcmp is deprecated; please use HASH_KEYCMP instead"
#else
#define uthash_memcmp(a,b,n) memcmp(a,b,n)
#ifndef HASH_FUNCTION
#define HASH_FUNCTION(keyptr,keylen,hashv) HASH_JEN(keyptr, keylen, hashv)
#endif
#ifndef HASH_KEYCMP
#define HASH_KEYCMP(a,b,n) uthash_memcmp(a,b,n)
#define HASH_KEYCMP(a,b,n) memcmp(a,b,n)
#endif
#ifndef uthash_noexpand_fyi
@@ -158,7 +148,7 @@ do {
#define HASH_VALUE(keyptr,keylen,hashv) \
do { \
HASH_FCN(keyptr, keylen, hashv); \
HASH_FUNCTION(keyptr, keylen, hashv); \
} while (0)
#define HASH_FIND_BYHASHVALUE(hh,head,keyptr,keylen,hashval,out) \
@@ -408,7 +398,7 @@ do {
do { \
IF_HASH_NONFATAL_OOM( int _ha_oomed = 0; ) \
(add)->hh.hashv = (hashval); \
(add)->hh.key = (char*) (keyptr); \
(add)->hh.key = (const void*) (keyptr); \
(add)->hh.keylen = (unsigned) (keylen_in); \
if (!(head)) { \
(add)->hh.next = NULL; \
@@ -590,13 +580,6 @@ do {
#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen)
#endif
/* default to Jenkin's hash unless overridden e.g. DHASH_FUNCTION=HASH_SAX */
#ifdef HASH_FUNCTION
#define HASH_FCN HASH_FUNCTION
#else
#define HASH_FCN HASH_JEN
#endif
/* The Bernstein hash function, used in Perl prior to v5.6. Note (x<<5+x)=x*33. */
#define HASH_BER(key,keylen,hashv) \
do { \
@@ -695,7 +678,8 @@ do {
case 4: _hj_i += ( (unsigned)_hj_key[3] << 24 ); /* FALLTHROUGH */ \
case 3: _hj_i += ( (unsigned)_hj_key[2] << 16 ); /* FALLTHROUGH */ \
case 2: _hj_i += ( (unsigned)_hj_key[1] << 8 ); /* FALLTHROUGH */ \
case 1: _hj_i += _hj_key[0]; \
case 1: _hj_i += _hj_key[0]; /* FALLTHROUGH */ \
default: ; \
} \
HASH_JEN_MIX(_hj_i, _hj_j, hashv); \
} while (0)
@@ -743,6 +727,8 @@ do {
case 1: hashv += *_sfh_key; \
hashv ^= hashv << 10; \
hashv += hashv >> 1; \
break; \
default: ; \
} \
\
/* Force "avalanching" of final 127 bits */ \
@@ -850,12 +836,12 @@ do {
struct UT_hash_handle *_he_thh, *_he_hh_nxt; \
UT_hash_bucket *_he_new_buckets, *_he_newbkt; \
_he_new_buckets = (UT_hash_bucket*)uthash_malloc( \
2UL * (tbl)->num_buckets * sizeof(struct UT_hash_bucket)); \
sizeof(struct UT_hash_bucket) * (tbl)->num_buckets * 2U); \
if (!_he_new_buckets) { \
HASH_RECORD_OOM(oomed); \
} else { \
uthash_bzero(_he_new_buckets, \
2UL * (tbl)->num_buckets * sizeof(struct UT_hash_bucket)); \
sizeof(struct UT_hash_bucket) * (tbl)->num_buckets * 2U); \
(tbl)->ideal_chain_maxlen = \
((tbl)->num_items >> ((tbl)->log2_num_buckets+1U)) + \
((((tbl)->num_items & (((tbl)->num_buckets*2U)-1U)) != 0U) ? 1U : 0U); \
@@ -1142,7 +1128,7 @@ typedef struct UT_hash_handle {
void *next; /* next element in app order */
struct UT_hash_handle *hh_prev; /* previous hh in bucket order */
struct UT_hash_handle *hh_next; /* next hh in bucket order */
void *key; /* ptr to enclosing struct's key */
const void *key; /* ptr to enclosing struct's key */
unsigned keylen; /* enclosing struct's key len */
unsigned hashv; /* result of hash-fcn(key) */
} UT_hash_handle;

View File

@@ -1,5 +1,5 @@
/*
Copyright (c) 2007-2018, Troy D. Hanson http://troydhanson.github.com/uthash/
Copyright (c) 2007-2021, Troy D. Hanson http://troydhanson.github.io/uthash/
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -24,7 +24,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef UTLIST_H
#define UTLIST_H
#define UTLIST_VERSION 2.1.0
#define UTLIST_VERSION 2.3.0
#include <assert.h>

View File

@@ -1,5 +1,5 @@
/*
Copyright (c) 2015-2018, Troy D. Hanson http://troydhanson.github.com/uthash/
Copyright (c) 2015-2021, Troy D. Hanson http://troydhanson.github.io/uthash/
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -26,7 +26,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef UTRINGBUFFER_H
#define UTRINGBUFFER_H
#define UTRINGBUFFER_VERSION 2.1.0
#define UTRINGBUFFER_VERSION 2.3.0
#include <stdlib.h>
#include <string.h>

View File

@@ -1,5 +1,5 @@
/*
Copyright (c) 2018-2018, Troy D. Hanson http://troydhanson.github.com/uthash/
Copyright (c) 2018-2021, Troy D. Hanson http://troydhanson.github.io/uthash/
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -24,7 +24,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef UTSTACK_H
#define UTSTACK_H
#define UTSTACK_VERSION 2.1.0
#define UTSTACK_VERSION 2.3.0
/*
* This file contains macros to manipulate a singly-linked list as a stack.
@@ -35,9 +35,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* struct item {
* int id;
* struct item *next;
* }
* };
*
* struct item *stack = NULL:
* struct item *stack = NULL;
*
* int main() {
* int count;

View File

@@ -1,5 +1,5 @@
/*
Copyright (c) 2008-2018, Troy D. Hanson http://troydhanson.github.com/uthash/
Copyright (c) 2008-2021, Troy D. Hanson http://troydhanson.github.io/uthash/
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -26,7 +26,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef UTSTRING_H
#define UTSTRING_H
#define UTSTRING_VERSION 2.1.0
#define UTSTRING_VERSION 2.3.0
#include <stdlib.h>
#include <string.h>

View File

@@ -12,7 +12,7 @@ PROGS = test1 test2 test3 test4 test5 test6 test7 test8 test9 \
test66 test67 test68 test69 test70 test71 test72 test73 \
test74 test75 test76 test77 test78 test79 test80 test81 \
test82 test83 test84 test85 test86 test87 test88 test89 \
test90 test91 test92 test93 test94 test95
test90 test91 test92 test93 test94 test95 test96
CFLAGS += -I$(HASHDIR)
#CFLAGS += -DHASH_BLOOM=16
#CFLAGS += -O2

View File

@@ -7,7 +7,7 @@ test2: make 10-item hash, lookup items with even keys, print
test3: make 10-item hash, delete items with even keys, print others
test4: 10 structs have dual hash handles, separate keys
test5: 10 structs have dual hash handles, lookup evens by alt key
test6: test alt malloc macros (and alt memcmp macro)
test6: test alt malloc macros (and alt key-comparison macro)
test7: test alt malloc macros with 1000 structs so bucket expansion occurs
test8: test num_items counter in UT_hash_handle
test9: test "find" after bucket expansion
@@ -89,10 +89,15 @@ test84: test HASH_REPLACE_STR with char* key
test85: test HASH_OVERHEAD on null and non null hash
test86: test *_APPEND_ELEM / *_PREPEND_ELEM (Thilo Schulz)
test87: test HASH_ADD_INORDER() macro (Thilo Schulz)
test88: test alt memcmp and strlen macros
test88: test alt key-comparison and strlen macros
test89: test code from the tinydtls project
test90: regression-test HASH_ADD_KEYPTR_INORDER (IronBug)
test91: test LL_INSERT_INORDER etc.
test92: HASH_NONFATAL_OOM
test93: alt_fatal
test94: utlist with fields named other than 'next' and 'prev'
test95: utstack
test96: HASH_FUNCTION + HASH_KEYCMP
Other Make targets
================================================================================

View File

@@ -1,25 +1,25 @@
#include <stdio.h> /* gets */
#include <stdio.h> /* printf */
#include <stdlib.h> /* atoi, malloc */
#include <string.h> /* strcpy */
#include "uthash.h"
struct my_struct {
int id; /* key */
char name[10];
char name[21];
UT_hash_handle hh; /* makes this structure hashable */
};
struct my_struct *users = NULL;
void add_user(int user_id, char *name)
void add_user(int user_id, const char *name)
{
struct my_struct *s;
HASH_FIND_INT(users, &user_id, s); /* id already in the hash? */
if (s == NULL) {
s = (struct my_struct*)malloc(sizeof(struct my_struct));
s = (struct my_struct*)malloc(sizeof *s);
s->id = user_id;
HASH_ADD_INT( users, id, s ); /* id: name of key field */
HASH_ADD_INT(users, id, s); /* id is the key field */
}
strcpy(s->name, name);
}
@@ -40,7 +40,8 @@ void delete_user(struct my_struct *user)
void delete_all()
{
struct my_struct *current_user, *tmp;
struct my_struct *current_user;
struct my_struct *tmp;
HASH_ITER(hh, users, current_user, tmp) {
HASH_DEL(users, current_user); /* delete it (users advances to next) */
@@ -57,36 +58,40 @@ void print_users()
}
}
int name_sort(struct my_struct *a, struct my_struct *b)
int by_name(const struct my_struct *a, const struct my_struct *b)
{
return strcmp(a->name, b->name);
}
int id_sort(struct my_struct *a, struct my_struct *b)
int by_id(const struct my_struct *a, const struct my_struct *b)
{
return (a->id - b->id);
}
void sort_by_name()
const char *getl(const char *prompt)
{
HASH_SORT(users, name_sort);
static char buf[21];
char *p;
printf("%s? ", prompt); fflush(stdout);
p = fgets(buf, sizeof(buf), stdin);
if (p == NULL || (p = strchr(buf, '\n')) == NULL) {
puts("Invalid input!");
exit(EXIT_FAILURE);
}
void sort_by_id()
{
HASH_SORT(users, id_sort);
*p = '\0';
return buf;
}
int main()
{
char in[10];
int id=1, running=1;
int id = 1;
int running = 1;
struct my_struct *s;
unsigned num_users;
int temp;
while (running) {
printf(" 1. add user\n");
printf(" 2. add/rename user by id\n");
printf(" 2. add or rename user by id\n");
printf(" 3. find user\n");
printf(" 4. delete user\n");
printf(" 5. delete all users\n");
@@ -95,27 +100,20 @@ int main()
printf(" 8. print users\n");
printf(" 9. count users\n");
printf("10. quit\n");
gets(in);
switch(atoi(in)) {
switch (atoi(getl("Command"))) {
case 1:
printf("name?\n");
add_user(id++, gets(in));
add_user(id++, getl("Name (20 char max)"));
break;
case 2:
printf("id?\n");
gets(in);
id = atoi(in);
printf("name?\n");
add_user(id, gets(in));
temp = atoi(getl("ID"));
add_user(temp, getl("Name (20 char max)"));
break;
case 3:
printf("id?\n");
s = find_user(atoi(gets(in)));
s = find_user(atoi(getl("ID to find")));
printf("user: %s\n", s ? s->name : "unknown");
break;
case 4:
printf("id?\n");
s = find_user(atoi(gets(in)));
s = find_user(atoi(getl("ID to delete")));
if (s) {
delete_user(s);
} else {
@@ -126,17 +124,17 @@ int main()
delete_all();
break;
case 6:
sort_by_name();
HASH_SORT(users, by_name);
break;
case 7:
sort_by_id();
HASH_SORT(users, by_id);
break;
case 8:
print_users();
break;
case 9:
num_users=HASH_COUNT(users);
printf("there are %u users\n", num_users);
temp = HASH_COUNT(users);
printf("there are %d users\n", temp);
break;
case 10:
running = 0;

View File

@@ -1,5 +1,5 @@
/*
Copyright (c) 2005-2018, Troy D. Hanson http://troydhanson.github.com/uthash/
Copyright (c) 2005-2021, Troy D. Hanson http://troydhanson.github.io/uthash/
All rights reserved.
Redistribution and use in source and binary forms, with or without

View File

@@ -12,9 +12,11 @@ sub usage {
usage if ((@ARGV == 0) or ($ARGV[0] eq '-h'));
my @exes = glob "$FindBin::Bin/keystat.???";
my @exes = glob "'$FindBin::Bin/keystat.???'";
my %stats;
for my $exe (@exes) {
$exe =~ s/\ /\\ /g;
$stats{$exe} = `$exe @ARGV`;
delete $stats{$exe} if ($? != 0); # omit hash functions that fail to produce stats (nx)
}

View File

@@ -47,5 +47,8 @@ int main()
HASH_FIND(alth,altusers,&i,sizeof(int),tmp);
printf("%d %s in alth\n", i, (tmp != NULL) ? "found" : "not found");
HASH_CLEAR(hh, users);
HASH_CLEAR(alth, altusers);
return 0;
}

View File

@@ -7,15 +7,16 @@
/* Set up macros for alternative malloc/free functions */
#undef uthash_malloc
#undef uthash_free
#undef uthash_memcmp
#undef uthash_strlen
#undef uthash_bzero
#define uthash_malloc(sz) alt_malloc(sz)
#define uthash_free(ptr,sz) alt_free(ptr,sz)
#define uthash_memcmp(a,b,n) alt_memcmp(a,b,n)
#define uthash_strlen(s) ..fail_to_compile..
#define uthash_bzero(a,n) alt_bzero(a,n)
#undef HASH_KEYCMP
#define HASH_KEYCMP(a,b,n) alt_keycmp(a,b,n)
typedef struct example_user_t {
int id;
int cookie;
@@ -41,10 +42,10 @@ static void alt_free(void *ptr, size_t sz)
free(ptr);
}
static int alt_memcmp_count = 0;
static int alt_memcmp(const void *a, const void *b, size_t n)
static int alt_keycmp_count = 0;
static int alt_keycmp(const void *a, const void *b, size_t n)
{
++alt_memcmp_count;
++alt_keycmp_count;
return memcmp(a,b,n);
}
@@ -115,7 +116,7 @@ int main()
#else
assert(alt_bzero_count == 2);
#endif
assert(alt_memcmp_count == 10);
assert(alt_keycmp_count == 10);
assert(alt_malloc_balance == 0);
return 0;
}

View File

@@ -3,7 +3,7 @@
#include "uthash.h"
// this is an example of how to do a LRU cache in C using uthash
// http://troydhanson.github.com/uthash/
// http://troydhanson.github.io/uthash/
// by Jehiah Czebotar 2011 - jehiah@gmail.com
// this code is in the public domain http://unlicense.org/

View File

@@ -8,8 +8,8 @@ int main()
char V_NeedleStr[] = "needle\0s";
long *V_KMP_Table;
long V_FindPos;
size_t V_StartPos;
size_t V_FindCnt;
size_t V_StartPos = 0;
size_t V_FindCnt = 0;
utstring_new(s);
@@ -24,9 +24,6 @@ int main()
if (V_KMP_Table != NULL) {
_utstring_BuildTable(utstring_body(t), utstring_len(t), V_KMP_Table);
V_FindCnt = 0;
V_FindPos = 0;
V_StartPos = 0;
do {
V_FindPos = _utstring_find(utstring_body(s) + V_StartPos,
utstring_len(s) - V_StartPos,

View File

@@ -9,7 +9,7 @@ int main()
long *V_KMP_Table;
long V_FindPos;
size_t V_StartPos;
size_t V_FindCnt;
size_t V_FindCnt = 0;
utstring_new(s);
@@ -24,8 +24,6 @@ int main()
if (V_KMP_Table != NULL) {
_utstring_BuildTableR(utstring_body(t), utstring_len(t), V_KMP_Table);
V_FindCnt = 0;
V_FindPos = 0;
V_StartPos = utstring_len(s) - 1;
do {
V_FindPos = _utstring_findR(utstring_body(s),

View File

@@ -9,22 +9,22 @@ alt_strlen
alt_strlen
alt_strlen
alt_strlen
alt_memcmp
alt_keycmp
alt_strlen
alt_memcmp
alt_keycmp
alt_strlen
alt_memcmp
alt_keycmp
alt_strlen
alt_memcmp
alt_keycmp
alt_strlen
alt_memcmp
alt_keycmp
alt_strlen
alt_memcmp
alt_keycmp
alt_strlen
alt_memcmp
alt_keycmp
alt_strlen
alt_memcmp
alt_keycmp
alt_strlen
alt_memcmp
alt_keycmp
alt_strlen
alt_memcmp
alt_keycmp

View File

@@ -8,9 +8,9 @@
/* This is mostly a copy of test6.c. */
#undef uthash_memcmp
#undef HASH_KEYCMP
#undef uthash_strlen
#define uthash_memcmp(a,b,n) alt_memcmp(a,b,n)
#define HASH_KEYCMP(a,b,n) alt_keycmp(a,b,n)
#define uthash_strlen(s) alt_strlen(s)
typedef struct example_user_t {
@@ -19,9 +19,9 @@ typedef struct example_user_t {
UT_hash_handle hh;
} example_user_t;
static int alt_memcmp(const void *a, const void *b, size_t n)
static int alt_keycmp(const void *a, const void *b, size_t n)
{
puts("alt_memcmp");
puts("alt_keycmp");
return memcmp(a,b,n);
}

View File

@@ -39,43 +39,39 @@ static void alt_fatal(char const * s) {
longjmp(j_buf, 1);
}
static example_user_t * init_user(int need_malloc_cnt) {
users = 0;
static void init_users(int need_malloc_cnt) {
users = NULL;
example_user_t * user = (example_user_t*)malloc(sizeof(example_user_t));
user->id = user_id;
is_fatal = 0;
malloc_cnt = need_malloc_cnt;
/* printf("adding to hash...\n"); */
if (!setjmp(j_buf)) {
HASH_ADD_INT(users, id, user);
} else {
free(user);
}
return user;
}
int main()
{
#define init(a) do { \
} while(0)
example_user_t *user;
user = init_user(3); /* bloom filter must fail */
init_users(3); /* bloom filter must fail */
if (!is_fatal) {
printf("fatal not called after bloom failure\n");
}
user = init_user(2); /* bucket creation must fail */
init_users(2); /* bucket creation must fail */
if (!is_fatal) {
printf("fatal not called after bucket creation failure\n");
}
user = init_user(1); /* table creation must fail */
init_users(1); /* table creation must fail */
if (!is_fatal) {
printf("fatal not called after table creation failure\n");
}
user = init_user(4); /* hash must create OK */
init_users(4); /* hash must create OK */
if (is_fatal) {
printf("fatal error when creating hash normally\n");
/* bad idea to continue running */
@@ -83,19 +79,20 @@ int main()
}
/* let's add users until expansion fails */
users = 0;
users = NULL;
malloc_cnt = 4;
while (1) {
user = (example_user_t*)malloc(sizeof(example_user_t));
user->id = user_id;
if (user_id++ == 1000) {
printf("there is no way 1000 iterations didn't require realloc\n");
break;
}
user = (example_user_t*)malloc(sizeof(example_user_t));
user->id = user_id;
if (!setjmp(j_buf)) {
HASH_ADD_INT(users, id, user);
} else {
free(user);
}
malloc_cnt = 0;
if (malloc_failed) {
if (!is_fatal) {
@@ -108,12 +105,12 @@ int main()
/* we can't really do anything, the hash is not in consistent
* state, so assume this is a success. */
break;
}
malloc_cnt = 0;
}
}
}
HASH_CLEAR(hh, users);
printf("End\n");
return 0;
}

40
dependencies/uthash/tests/test96.ans vendored Normal file
View File

@@ -0,0 +1,40 @@
time 56 not found, inserting it
time 7 not found, inserting it
time 10 not found, inserting it
time 39 not found, inserting it
time 82 found with value 10
time 15 found with value 39
time 31 found with value 7
time 26 not found, inserting it
time 51 found with value 39
time 83 not found, inserting it
time 46 found with value 10
time 92 found with value 56
time 49 not found, inserting it
time 25 found with value 49
time 80 found with value 56
time 54 not found, inserting it
time 97 found with value 49
time 9 not found, inserting it
time 34 found with value 10
time 86 found with value 26
time 87 found with value 39
time 28 not found, inserting it
time 13 found with value 49
time 91 found with value 7
time 95 found with value 83
time 63 found with value 39
time 71 found with value 83
time 100 found with value 28
time 44 found with value 56
time 42 found with value 54
time 16 found with value 28
time 32 found with value 56
time 6 found with value 54
time 85 found with value 49
time 40 found with value 28
time 20 found with value 56
time 18 found with value 54
time 99 found with value 39
time 22 found with value 10
time 1 found with value 49

48
dependencies/uthash/tests/test96.c vendored Normal file
View File

@@ -0,0 +1,48 @@
#include <stdio.h>
#include <stdlib.h>
#define HASH_FUNCTION(a,n,hv) (hv = clockface_hash(*(const int*)(a)))
#define HASH_KEYCMP(a,b,n) clockface_neq(*(const int*)(a), *(const int*)(b))
#include "uthash.h"
struct clockface {
int time;
UT_hash_handle hh;
};
int clockface_hash(int time)
{
return (time % 4);
}
int clockface_neq(int t1, int t2)
{
return ((t1 % 12) != (t2 % 12));
}
int main()
{
int random_data[] = {
56, 7, 10, 39, 82, 15, 31, 26, 51, 83,
46, 92, 49, 25, 80, 54, 97, 9, 34, 86,
87, 28, 13, 91, 95, 63, 71, 100, 44, 42,
16, 32, 6, 85, 40, 20, 18, 99, 22, 1
};
struct clockface *times = NULL;
for (int i=0; i < 40; ++i) {
struct clockface *elt = (struct clockface *)malloc(sizeof(*elt));
struct clockface *found = NULL;
elt->time = random_data[i];
HASH_FIND_INT(times, &elt->time, found);
if (found) {
printf("time %d found with value %d\n", elt->time, found->time);
} else {
printf("time %d not found, inserting it\n", elt->time);
HASH_ADD_INT(times, time, elt);
}
}
return 0;
}