mirror of
https://github.com/optim-enterprises-bv/nDPId.git
synced 2025-10-29 09:22:23 +00:00
Merge commit '1fa53c5bf8d0717f784c79abaa5111f88ab00221'
This commit is contained in:
2
dependencies/uthash/.travis.yml
vendored
2
dependencies/uthash/.travis.yml
vendored
@@ -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
|
||||
|
||||
2
dependencies/uthash/LICENSE
vendored
2
dependencies/uthash/LICENSE
vendored
@@ -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
|
||||
|
||||
4
dependencies/uthash/README.md
vendored
4
dependencies/uthash/README.md
vendored
@@ -1,8 +1,8 @@
|
||||
|
||||
[](https://travis-ci.org/troydhanson/uthash)
|
||||
[](https://travis-ci.org/troydhanson/uthash)
|
||||
|
||||
Documentation for uthash is available at:
|
||||
|
||||
http://troydhanson.github.com/uthash/
|
||||
https://troydhanson.github.io/uthash/
|
||||
|
||||
|
||||
|
||||
17
dependencies/uthash/doc/ChangeLog.txt
vendored
17
dependencies/uthash/doc/ChangeLog.txt
vendored
@@ -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
|
||||
|
||||
|
||||
8
dependencies/uthash/doc/index.html
vendored
8
dependencies/uthash/doc/index.html
vendored
@@ -14,7 +14,7 @@
|
||||
|
||||
<div id="topnav">
|
||||
<a href="http://github.com/troydhanson/uthash">GitHub page</a> >
|
||||
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>
|
||||
@@ -72,7 +72,7 @@ struct my_struct {
|
||||
struct my_struct *users = NULL;
|
||||
|
||||
void add_user(struct my_struct *s) {
|
||||
HASH_ADD_INT( users, id, s );
|
||||
HASH_ADD_INT(users, id, s);
|
||||
}
|
||||
|
||||
</pre>
|
||||
@@ -86,7 +86,7 @@ Example 2. Looking up an item in a hash.
|
||||
struct my_struct *find_user(int user_id) {
|
||||
struct my_struct *s;
|
||||
|
||||
HASH_FIND_INT( users, &user_id, s );
|
||||
HASH_FIND_INT(users, &user_id, s);
|
||||
return s;
|
||||
}
|
||||
|
||||
@@ -100,7 +100,7 @@ Example 3. Deleting an item from a hash.
|
||||
|
||||
<pre>
|
||||
void delete_user(struct my_struct *user) {
|
||||
HASH_DEL( users, user);
|
||||
HASH_DEL(users, user);
|
||||
}
|
||||
|
||||
</pre>
|
||||
|
||||
4
dependencies/uthash/doc/license.html
vendored
4
dependencies/uthash/doc/license.html
vendored
@@ -13,7 +13,7 @@
|
||||
</div> <!-- banner -->
|
||||
|
||||
<div id="topnav">
|
||||
<a href="http://troydhanson.github.com/uthash/">uthash home</a> >
|
||||
<a href="http://troydhanson.github.io/uthash/">uthash home</a> >
|
||||
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
|
||||
|
||||
222
dependencies/uthash/doc/userguide.txt
vendored
222
dependencies/uthash/doc/userguide.txt
vendored
@@ -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,10 +215,10 @@ 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 */
|
||||
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
|
||||
@@ -256,10 +256,10 @@ Otherwise we just modify the structure that already exists.
|
||||
struct my_struct *s;
|
||||
|
||||
HASH_FIND_INT(users, &user_id, s); /* id already in the hash? */
|
||||
if (s==NULL) {
|
||||
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: name of key field */
|
||||
}
|
||||
strcpy(s->name, name);
|
||||
}
|
||||
@@ -284,7 +284,7 @@ right.
|
||||
/* bad */
|
||||
void add_user(struct my_struct *users, int user_id, char *name) {
|
||||
...
|
||||
HASH_ADD_INT( users, id, s );
|
||||
HASH_ADD_INT(users, id, s);
|
||||
}
|
||||
|
||||
You really need to pass 'a pointer' to the hash pointer:
|
||||
@@ -292,7 +292,7 @@ You really need to pass 'a pointer' to the hash pointer:
|
||||
/* good */
|
||||
void add_user(struct my_struct **users, int user_id, char *name) { ...
|
||||
...
|
||||
HASH_ADD_INT( *users, id, s );
|
||||
HASH_ADD_INT(*users, id, s);
|
||||
}
|
||||
|
||||
Note that we dereferenced the pointer in the `HASH_ADD` also.
|
||||
@@ -319,7 +319,7 @@ To look up a structure in a hash, you need its key. Then call `HASH_FIND`.
|
||||
struct my_struct *find_user(int user_id) {
|
||||
struct my_struct *s;
|
||||
|
||||
HASH_FIND_INT( users, &user_id, s ); /* s: output pointer */
|
||||
HASH_FIND_INT(users, &user_id, s); /* s: output pointer */
|
||||
return s;
|
||||
}
|
||||
----------------------------------------------------------------------
|
||||
@@ -376,8 +376,8 @@ void delete_all() {
|
||||
struct my_struct *current_user, *tmp;
|
||||
|
||||
HASH_ITER(hh, users, current_user, tmp) {
|
||||
HASH_DEL(users,current_user); /* delete; users advances to next */
|
||||
free(current_user); /* optional- if you want to free */
|
||||
HASH_DEL(users, current_user); /* delete; users advances to next */
|
||||
free(current_user); /* optional- if you want to free */
|
||||
}
|
||||
}
|
||||
----------------------------------------------------------------------
|
||||
@@ -387,7 +387,7 @@ All-at-once deletion
|
||||
If you only want to delete all the items, but not free them or do any
|
||||
per-element clean up, you can do this more efficiently in a single operation:
|
||||
|
||||
HASH_CLEAR(hh,users);
|
||||
HASH_CLEAR(hh, users);
|
||||
|
||||
Afterward, the list head (here, `users`) will be set to `NULL`.
|
||||
|
||||
@@ -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
|
||||
@@ -417,7 +417,7 @@ following the `hh.next` pointer.
|
||||
void print_users() {
|
||||
struct my_struct *s;
|
||||
|
||||
for(s=users; s != NULL; s=s->hh.next) {
|
||||
for (s = users; s != NULL; s = s->hh.next) {
|
||||
printf("user id %d: name %s\n", s->id, s->name);
|
||||
}
|
||||
}
|
||||
@@ -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,14 +452,14 @@ 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
|
||||
^^^^^^^
|
||||
The items in the hash are visited in "insertion order" when you follow the
|
||||
`hh.next` pointer. You can sort the items into a new order using `HASH_SORT`.
|
||||
|
||||
HASH_SORT( users, name_sort );
|
||||
HASH_SORT(users, name_sort);
|
||||
|
||||
The second argument is a pointer to a comparison function. It must accept two
|
||||
pointer arguments (the items to compare), and must return an `int` which is
|
||||
@@ -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) {
|
||||
return strcmp(a->name,b->name);
|
||||
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,85 +516,100 @@ 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 */
|
||||
if (s == NULL) {
|
||||
s = (struct my_struct*)malloc(sizeof *s);
|
||||
s->id = user_id;
|
||||
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 */
|
||||
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) */
|
||||
free(current_user); /* free it */
|
||||
}
|
||||
HASH_ITER(hh, users, current_user, tmp) {
|
||||
HASH_DEL(users, current_user); /* delete it (users advances to next) */
|
||||
free(current_user); /* free it */
|
||||
}
|
||||
}
|
||||
|
||||
void print_users() {
|
||||
void print_users()
|
||||
{
|
||||
struct my_struct *s;
|
||||
|
||||
for(s=users; s != NULL; s=(struct my_struct*)(s->hh.next)) {
|
||||
for (s = users; s != NULL; s = (struct my_struct*)(s->hh.next)) {
|
||||
printf("user id %d: name %s\n", s->id, s->name);
|
||||
}
|
||||
}
|
||||
|
||||
int name_sort(struct my_struct *a, struct my_struct *b) {
|
||||
return strcmp(a->name,b->name);
|
||||
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,47 +618,44 @@ 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;
|
||||
running = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -720,10 +732,10 @@ int main(int argc, char *argv[]) {
|
||||
s = (struct my_struct *)malloc(sizeof *s);
|
||||
strcpy(s->name, names[i]);
|
||||
s->id = i;
|
||||
HASH_ADD_STR( users, name, s );
|
||||
HASH_ADD_STR(users, name, s);
|
||||
}
|
||||
|
||||
HASH_FIND_STR( users, "betty", s);
|
||||
HASH_FIND_STR(users, "betty", s);
|
||||
if (s) printf("betty's id is %d\n", s->id);
|
||||
|
||||
/* free the hash table contents */
|
||||
@@ -766,10 +778,10 @@ int main(int argc, char *argv[]) {
|
||||
s = (struct my_struct *)malloc(sizeof *s);
|
||||
s->name = names[i];
|
||||
s->id = i;
|
||||
HASH_ADD_KEYPTR( hh, users, s->name, strlen(s->name), s );
|
||||
HASH_ADD_KEYPTR(hh, users, s->name, strlen(s->name), s);
|
||||
}
|
||||
|
||||
HASH_FIND_STR( users, "betty", s);
|
||||
HASH_FIND_STR(users, "betty", s);
|
||||
if (s) printf("betty's id is %d\n", s->id);
|
||||
|
||||
/* free the hash table contents */
|
||||
@@ -812,12 +824,12 @@ int main() {
|
||||
if (!e) return -1;
|
||||
e->key = (void*)someaddr;
|
||||
e->i = 1;
|
||||
HASH_ADD_PTR(hash,key,e);
|
||||
HASH_ADD_PTR(hash, key, e);
|
||||
HASH_FIND_PTR(hash, &someaddr, d);
|
||||
if (d) printf("found\n");
|
||||
|
||||
/* release memory */
|
||||
HASH_DEL(hash,e);
|
||||
HASH_DEL(hash, e);
|
||||
free(e);
|
||||
return 0;
|
||||
}
|
||||
@@ -924,7 +936,7 @@ int main(int argc, char *argv[]) {
|
||||
int beijing[] = {0x5317, 0x4eac}; /* UTF-32LE for 北京 */
|
||||
|
||||
/* allocate and initialize our structure */
|
||||
msg = (msg_t *)malloc( sizeof(msg_t) + sizeof(beijing) );
|
||||
msg = (msg_t *)malloc(sizeof(msg_t) + sizeof(beijing));
|
||||
memset(msg, 0, sizeof(msg_t)+sizeof(beijing)); /* zero fill */
|
||||
msg->len = sizeof(beijing);
|
||||
msg->encoding = UTF32;
|
||||
@@ -936,16 +948,16 @@ int main(int argc, char *argv[]) {
|
||||
- offsetof(msg_t, encoding); /* offset of first key field */
|
||||
|
||||
/* add our structure to the hash table */
|
||||
HASH_ADD( hh, msgs, encoding, keylen, msg);
|
||||
HASH_ADD(hh, msgs, encoding, keylen, msg);
|
||||
|
||||
/* look it up to prove that it worked :-) */
|
||||
msg=NULL;
|
||||
msg = NULL;
|
||||
|
||||
lookup_key = (lookup_key_t *)malloc(sizeof(*lookup_key) + sizeof(beijing));
|
||||
memset(lookup_key, 0, sizeof(*lookup_key) + sizeof(beijing));
|
||||
lookup_key->encoding = UTF32;
|
||||
memcpy(lookup_key->text, beijing, sizeof(beijing));
|
||||
HASH_FIND( hh, msgs, &lookup_key->encoding, keylen, msg );
|
||||
HASH_FIND(hh, msgs, &lookup_key->encoding, keylen, msg);
|
||||
if (msg) printf("found \n");
|
||||
free(lookup_key);
|
||||
|
||||
@@ -1028,7 +1040,7 @@ typedef struct item {
|
||||
UT_hash_handle hh;
|
||||
} item_t;
|
||||
|
||||
item_t *items=NULL;
|
||||
item_t *items = NULL;
|
||||
|
||||
int main(int argc, char *argvp[]) {
|
||||
item_t *item1, *item2, *tmp1, *tmp2;
|
||||
@@ -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");
|
||||
|
||||
@@ -1128,7 +1140,7 @@ always used with the `users_by_name` hash table).
|
||||
HASH_ADD(hh2, users_by_name, username, strlen(s->username), s);
|
||||
|
||||
/* find user by ID in the "users_by_id" hash table */
|
||||
i=1;
|
||||
i = 1;
|
||||
HASH_FIND(hh1, users_by_id, &i, sizeof(int), s);
|
||||
if (s) printf("found id %d: %s\n", i, s->username);
|
||||
|
||||
@@ -1155,7 +1167,7 @@ The `HASH_ADD_INORDER*` macros work just like their `HASH_ADD*` counterparts, bu
|
||||
with an additional comparison-function argument:
|
||||
|
||||
int name_sort(struct my_struct *a, struct my_struct *b) {
|
||||
return strcmp(a->name,b->name);
|
||||
return strcmp(a->name, b->name);
|
||||
}
|
||||
|
||||
HASH_ADD_KEYPTR_INORDER(hh, items, &item->name, strlen(item->name), item, name_sort);
|
||||
@@ -1183,7 +1195,7 @@ Now we can define two sort functions, then use `HASH_SRT`.
|
||||
}
|
||||
|
||||
int sort_by_name(struct my_struct *a, struct my_struct *b) {
|
||||
return strcmp(a->username,b->username);
|
||||
return strcmp(a->username, b->username);
|
||||
}
|
||||
|
||||
HASH_SRT(hh1, users_by_id, sort_by_id);
|
||||
@@ -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;
|
||||
@@ -1252,25 +1265,26 @@ Now suppose we have added some users, and want to select just the administrator
|
||||
users who have id's less than 1024.
|
||||
|
||||
#define is_admin(x) (((user_t*)x)->id < 1024)
|
||||
HASH_SELECT(ah,admins,hh,users,is_admin);
|
||||
HASH_SELECT(ah, admins, hh, users, is_admin);
|
||||
|
||||
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
|
||||
@@ -1290,7 +1304,7 @@ that do not provide `memcmp`, you can substitute your own implementation.
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
#undef HASH_KEYCMP
|
||||
#define HASH_KEYCMP(a,b,len) bcmp(a,b,len)
|
||||
#define HASH_KEYCMP(a,b,len) bcmp(a, b, len)
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
Another reason to substitute your own key comparison function is if your "key" is not
|
||||
@@ -1631,7 +1645,7 @@ If your application uses its own custom allocator, uthash can use them too.
|
||||
|
||||
/* re-define, specifying alternate functions */
|
||||
#define uthash_malloc(sz) my_malloc(sz)
|
||||
#define uthash_free(ptr,sz) my_free(ptr)
|
||||
#define uthash_free(ptr, sz) my_free(ptr)
|
||||
|
||||
...
|
||||
----------------------------------------------------------------------------
|
||||
@@ -1647,7 +1661,7 @@ provide these functions, you can substitute your own implementations.
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
#undef uthash_bzero
|
||||
#define uthash_bzero(a,len) my_bzero(a,len)
|
||||
#define uthash_bzero(a, len) my_bzero(a, len)
|
||||
|
||||
#undef uthash_strlen
|
||||
#define uthash_strlen(s) my_strlen(s)
|
||||
@@ -1754,7 +1768,7 @@ concurrent readers (since uthash 1.5).
|
||||
For example using pthreads you can create an rwlock like this:
|
||||
|
||||
pthread_rwlock_t lock;
|
||||
if (pthread_rwlock_init(&lock,NULL) != 0) fatal("can't create rwlock");
|
||||
if (pthread_rwlock_init(&lock, NULL) != 0) fatal("can't create rwlock");
|
||||
|
||||
Then, readers must acquire the read lock before doing any `HASH_FIND` calls or
|
||||
before iterating over the hash elements:
|
||||
@@ -1795,10 +1809,10 @@ 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)
|
||||
|HASH_REPLACE_STR | (head, keyfield_name, item_ptr, replaced_item_ptr)
|
||||
|HASH_FIND_STR | (head, key_ptr, item_ptr)
|
||||
|HASH_ADD_PTR | (head, keyfield_name, item_ptr)
|
||||
|HASH_REPLACE_PTR | (head, keyfield_name, item_ptr, replaced_item_ptr)
|
||||
|
||||
2
dependencies/uthash/doc/utarray.txt
vendored
2
dependencies/uthash/doc/utarray.txt
vendored
@@ -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].
|
||||
|
||||
|
||||
2
dependencies/uthash/doc/utlist.txt
vendored
2
dependencies/uthash/doc/utlist.txt
vendored
@@ -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].
|
||||
|
||||
|
||||
2
dependencies/uthash/doc/utringbuffer.txt
vendored
2
dependencies/uthash/doc/utringbuffer.txt
vendored
@@ -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].
|
||||
|
||||
|
||||
2
dependencies/uthash/doc/utstack.txt
vendored
2
dependencies/uthash/doc/utstack.txt
vendored
@@ -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].
|
||||
|
||||
|
||||
2
dependencies/uthash/doc/utstring.txt
vendored
2
dependencies/uthash/doc/utstring.txt
vendored
@@ -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].
|
||||
|
||||
|
||||
2
dependencies/uthash/package.json
vendored
2
dependencies/uthash/package.json
vendored
@@ -24,5 +24,5 @@
|
||||
"src/utstring.h"
|
||||
],
|
||||
|
||||
"version": "2.1.0"
|
||||
"version": "2.3.0"
|
||||
}
|
||||
|
||||
9
dependencies/uthash/src/utarray.h
vendored
9
dependencies/uthash/src/utarray.h
vendored
@@ -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;
|
||||
|
||||
64
dependencies/uthash/src/uthash.h
vendored
64
dependencies/uthash/src/uthash.h
vendored
@@ -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 */ \
|
||||
@@ -764,7 +750,7 @@ do {
|
||||
} \
|
||||
while ((out) != NULL) { \
|
||||
if ((out)->hh.hashv == (hashval) && (out)->hh.keylen == (keylen_in)) { \
|
||||
if (HASH_KEYCMP((out)->hh.key, keyptr, keylen_in) == 0) { \
|
||||
if (HASH_KEYCMP((out)->hh.key, keyptr, keylen_in) == 0) { \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
@@ -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;
|
||||
|
||||
4
dependencies/uthash/src/utlist.h
vendored
4
dependencies/uthash/src/utlist.h
vendored
@@ -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>
|
||||
|
||||
|
||||
4
dependencies/uthash/src/utringbuffer.h
vendored
4
dependencies/uthash/src/utringbuffer.h
vendored
@@ -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>
|
||||
|
||||
8
dependencies/uthash/src/utstack.h
vendored
8
dependencies/uthash/src/utstack.h
vendored
@@ -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;
|
||||
|
||||
4
dependencies/uthash/src/utstring.h
vendored
4
dependencies/uthash/src/utstring.h
vendored
@@ -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>
|
||||
|
||||
2
dependencies/uthash/tests/Makefile
vendored
2
dependencies/uthash/tests/Makefile
vendored
@@ -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
|
||||
|
||||
9
dependencies/uthash/tests/README
vendored
9
dependencies/uthash/tests/README
vendored
@@ -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
|
||||
================================================================================
|
||||
|
||||
86
dependencies/uthash/tests/example.c
vendored
86
dependencies/uthash/tests/example.c
vendored
@@ -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));
|
||||
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);
|
||||
}
|
||||
@@ -28,23 +28,24 @@ struct my_struct *find_user(int user_id)
|
||||
{
|
||||
struct my_struct *s;
|
||||
|
||||
HASH_FIND_INT( users, &user_id, s ); /* s: output pointer */
|
||||
HASH_FIND_INT(users, &user_id, s); /* s: output pointer */
|
||||
return s;
|
||||
}
|
||||
|
||||
void delete_user(struct my_struct *user)
|
||||
{
|
||||
HASH_DEL( users, user); /* user: pointer to deletee */
|
||||
HASH_DEL(users, user); /* user: pointer to deletee */
|
||||
free(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) */
|
||||
free(current_user); /* free it */
|
||||
HASH_DEL(users, current_user); /* delete it (users advances to next) */
|
||||
free(current_user); /* free it */
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,41 +53,45 @@ void print_users()
|
||||
{
|
||||
struct my_struct *s;
|
||||
|
||||
for(s=users; s != NULL; s=(struct my_struct*)(s->hh.next)) {
|
||||
for (s = users; s != NULL; s = (struct my_struct*)(s->hh.next)) {
|
||||
printf("user id %d: name %s\n", s->id, s->name);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
||||
void sort_by_id()
|
||||
{
|
||||
HASH_SORT(users, id_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);
|
||||
}
|
||||
*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,20 +124,20 @@ 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;
|
||||
running = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
2
dependencies/uthash/tests/hashscan.c
vendored
2
dependencies/uthash/tests/hashscan.c
vendored
@@ -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
|
||||
|
||||
4
dependencies/uthash/tests/keystats
vendored
4
dependencies/uthash/tests/keystats
vendored
@@ -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)
|
||||
}
|
||||
|
||||
3
dependencies/uthash/tests/test10.c
vendored
3
dependencies/uthash/tests/test10.c
vendored
@@ -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;
|
||||
}
|
||||
|
||||
13
dependencies/uthash/tests/test6.c
vendored
13
dependencies/uthash/tests/test6.c
vendored
@@ -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;
|
||||
}
|
||||
|
||||
2
dependencies/uthash/tests/test65.c
vendored
2
dependencies/uthash/tests/test65.c
vendored
@@ -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/
|
||||
|
||||
|
||||
7
dependencies/uthash/tests/test76.c
vendored
7
dependencies/uthash/tests/test76.c
vendored
@@ -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,
|
||||
|
||||
4
dependencies/uthash/tests/test77.c
vendored
4
dependencies/uthash/tests/test77.c
vendored
@@ -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),
|
||||
|
||||
20
dependencies/uthash/tests/test88.ans
vendored
20
dependencies/uthash/tests/test88.ans
vendored
@@ -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
|
||||
|
||||
8
dependencies/uthash/tests/test88.c
vendored
8
dependencies/uthash/tests/test88.c
vendored
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
37
dependencies/uthash/tests/test93.c
vendored
37
dependencies/uthash/tests/test93.c
vendored
@@ -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()
|
||||
{
|
||||
example_user_t *user;
|
||||
|
||||
#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
40
dependencies/uthash/tests/test96.ans
vendored
Normal 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
48
dependencies/uthash/tests/test96.c
vendored
Normal 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;
|
||||
}
|
||||
Reference in New Issue
Block a user