mirror of
https://github.com/chatmail/core.git
synced 2026-04-28 10:56:29 +03:00
inital commit
This commit is contained in:
916
src/dc_hash.rs
Normal file
916
src/dc_hash.rs
Normal file
@@ -0,0 +1,916 @@
|
||||
use libc;
|
||||
extern "C" {
|
||||
#[no_mangle]
|
||||
fn __assert_rtn(
|
||||
_: *const libc::c_char,
|
||||
_: *const libc::c_char,
|
||||
_: libc::c_int,
|
||||
_: *const libc::c_char,
|
||||
) -> !;
|
||||
#[no_mangle]
|
||||
fn malloc(_: libc::c_ulong) -> *mut libc::c_void;
|
||||
#[no_mangle]
|
||||
fn free(_: *mut libc::c_void);
|
||||
#[no_mangle]
|
||||
fn memcmp(_: *const libc::c_void, _: *const libc::c_void, _: libc::c_ulong) -> libc::c_int;
|
||||
#[no_mangle]
|
||||
fn memcpy(_: *mut libc::c_void, _: *const libc::c_void, _: libc::c_ulong) -> *mut libc::c_void;
|
||||
#[no_mangle]
|
||||
fn memset(_: *mut libc::c_void, _: libc::c_int, _: libc::c_ulong) -> *mut libc::c_void;
|
||||
#[no_mangle]
|
||||
fn strlen(_: *const libc::c_char) -> libc::c_ulong;
|
||||
}
|
||||
pub type uintptr_t = libc::c_ulong;
|
||||
/* A complete hash table is an instance of the following structure.
|
||||
* The internals of this structure are intended to be opaque -- client
|
||||
* code should not attempt to access or modify the fields of this structure
|
||||
* directly. Change this structure only by using the routines below.
|
||||
* However, many of the "procedures" and "functions" for modifying and
|
||||
* accessing this structure are really macros, so we can't really make
|
||||
* this structure opaque.
|
||||
*/
|
||||
#[derive(Copy, Clone)]
|
||||
#[repr(C)]
|
||||
pub struct _dc_hash {
|
||||
pub keyClass: libc::c_char,
|
||||
pub copyKey: libc::c_char,
|
||||
pub count: libc::c_int,
|
||||
pub first: *mut dc_hashelem_t,
|
||||
pub htsize: libc::c_int,
|
||||
pub ht: *mut _ht,
|
||||
}
|
||||
#[derive(Copy, Clone)]
|
||||
#[repr(C)]
|
||||
pub struct _ht {
|
||||
pub count: libc::c_int,
|
||||
pub chain: *mut dc_hashelem_t,
|
||||
}
|
||||
pub type dc_hashelem_t = _dc_hashelem;
|
||||
/* Each element in the hash table is an instance of the following
|
||||
* structure. All elements are stored on a single doubly-linked list.
|
||||
*
|
||||
* Again, this structure is intended to be opaque, but it can't really
|
||||
* be opaque because it is used by macros.
|
||||
*/
|
||||
#[derive(Copy, Clone)]
|
||||
#[repr(C)]
|
||||
pub struct _dc_hashelem {
|
||||
pub next: *mut dc_hashelem_t,
|
||||
pub prev: *mut dc_hashelem_t,
|
||||
pub data: *mut libc::c_void,
|
||||
pub pKey: *mut libc::c_void,
|
||||
pub nKey: libc::c_int,
|
||||
}
|
||||
/* Forward declarations of structures.
|
||||
*/
|
||||
pub type dc_hash_t = _dc_hash;
|
||||
/*
|
||||
* There are 4 different modes of operation for a hash table:
|
||||
*
|
||||
* DC_HASH_INT nKey is used as the key and pKey is ignored.
|
||||
*
|
||||
* DC_HASH_POINTER pKey is used as the key and nKey is ignored.
|
||||
*
|
||||
* DC_HASH_STRING pKey points to a string that is nKey bytes long
|
||||
* (including the null-terminator, if any). Case
|
||||
* is ignored in comparisons.
|
||||
*
|
||||
* DC_HASH_BINARY pKey points to binary data nKey bytes long.
|
||||
* memcmp() is used to compare keys.
|
||||
*
|
||||
* A copy of the key is made for DC_HASH_STRING and DC_HASH_BINARY
|
||||
* if the copyKey parameter to dc_hash_init() is 1.
|
||||
*/
|
||||
/*
|
||||
* Just to make the last parameter of dc_hash_init() more readable.
|
||||
*/
|
||||
/*
|
||||
* Access routines. To delete an element, insert a NULL pointer.
|
||||
*/
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_hash_init(
|
||||
mut pNew: *mut dc_hash_t,
|
||||
mut keyClass: libc::c_int,
|
||||
mut copyKey: libc::c_int,
|
||||
) {
|
||||
if 0 != pNew.is_null() as libc::c_int as libc::c_long {
|
||||
__assert_rtn(
|
||||
(*::std::mem::transmute::<&[u8; 13], &[libc::c_char; 13]>(b"dc_hash_init\x00"))
|
||||
.as_ptr(),
|
||||
b"../src/dc_hash.c\x00" as *const u8 as *const libc::c_char,
|
||||
93i32,
|
||||
b"pNew!=0\x00" as *const u8 as *const libc::c_char,
|
||||
);
|
||||
} else {
|
||||
};
|
||||
if 0 != !(keyClass >= 1i32 && keyClass <= 4i32) as libc::c_int as libc::c_long {
|
||||
__assert_rtn(
|
||||
(*::std::mem::transmute::<&[u8; 13], &[libc::c_char; 13]>(b"dc_hash_init\x00"))
|
||||
.as_ptr(),
|
||||
b"../src/dc_hash.c\x00" as *const u8 as *const libc::c_char,
|
||||
94i32,
|
||||
b"keyClass>=DC_HASH_INT && keyClass<=DC_HASH_BINARY\x00" as *const u8
|
||||
as *const libc::c_char,
|
||||
);
|
||||
} else {
|
||||
};
|
||||
(*pNew).keyClass = keyClass as libc::c_char;
|
||||
if keyClass == 2i32 || keyClass == 1i32 {
|
||||
copyKey = 0i32
|
||||
}
|
||||
(*pNew).copyKey = copyKey as libc::c_char;
|
||||
(*pNew).first = 0 as *mut dc_hashelem_t;
|
||||
(*pNew).count = 0i32;
|
||||
(*pNew).htsize = 0i32;
|
||||
(*pNew).ht = 0 as *mut _ht;
|
||||
}
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_hash_insert(
|
||||
mut pH: *mut dc_hash_t,
|
||||
mut pKey: *const libc::c_void,
|
||||
mut nKey: libc::c_int,
|
||||
mut data: *mut libc::c_void,
|
||||
) -> *mut libc::c_void {
|
||||
/* Raw hash value of the key */
|
||||
let mut hraw: libc::c_int = 0;
|
||||
/* the hash of the key modulo hash table size */
|
||||
let mut h: libc::c_int = 0;
|
||||
/* Used to loop thru the element list */
|
||||
let mut elem: *mut dc_hashelem_t = 0 as *mut dc_hashelem_t;
|
||||
/* New element added to the pH */
|
||||
let mut new_elem: *mut dc_hashelem_t = 0 as *mut dc_hashelem_t;
|
||||
/* The hash function */
|
||||
let mut xHash: Option<
|
||||
unsafe extern "C" fn(_: *const libc::c_void, _: libc::c_int) -> libc::c_int,
|
||||
> = None;
|
||||
if 0 != pH.is_null() as libc::c_int as libc::c_long {
|
||||
__assert_rtn(
|
||||
(*::std::mem::transmute::<&[u8; 15], &[libc::c_char; 15]>(b"dc_hash_insert\x00"))
|
||||
.as_ptr(),
|
||||
b"../src/dc_hash.c\x00" as *const u8 as *const libc::c_char,
|
||||
429i32,
|
||||
b"pH!=0\x00" as *const u8 as *const libc::c_char,
|
||||
);
|
||||
} else {
|
||||
};
|
||||
xHash = hashFunction((*pH).keyClass as libc::c_int);
|
||||
if 0 != xHash.is_none() as libc::c_int as libc::c_long {
|
||||
__assert_rtn(
|
||||
(*::std::mem::transmute::<&[u8; 15], &[libc::c_char; 15]>(b"dc_hash_insert\x00"))
|
||||
.as_ptr(),
|
||||
b"../src/dc_hash.c\x00" as *const u8 as *const libc::c_char,
|
||||
431i32,
|
||||
b"xHash!=0\x00" as *const u8 as *const libc::c_char,
|
||||
);
|
||||
} else {
|
||||
};
|
||||
hraw = xHash.expect("non-null function pointer")(pKey, nKey);
|
||||
if 0 != !((*pH).htsize & (*pH).htsize - 1i32 == 0i32) as libc::c_int as libc::c_long {
|
||||
__assert_rtn(
|
||||
(*::std::mem::transmute::<&[u8; 15], &[libc::c_char; 15]>(b"dc_hash_insert\x00"))
|
||||
.as_ptr(),
|
||||
b"../src/dc_hash.c\x00" as *const u8 as *const libc::c_char,
|
||||
433i32,
|
||||
b"(pH->htsize & (pH->htsize-1))==0\x00" as *const u8 as *const libc::c_char,
|
||||
);
|
||||
} else {
|
||||
};
|
||||
h = hraw & (*pH).htsize - 1i32;
|
||||
elem = findElementGivenHash(pH, pKey, nKey, h);
|
||||
if !elem.is_null() {
|
||||
let mut old_data: *mut libc::c_void = (*elem).data;
|
||||
if data.is_null() {
|
||||
removeElementGivenHash(pH, elem, h);
|
||||
} else {
|
||||
(*elem).data = data
|
||||
}
|
||||
return old_data;
|
||||
}
|
||||
if data.is_null() {
|
||||
return 0 as *mut libc::c_void;
|
||||
}
|
||||
new_elem = sjhashMalloc(::std::mem::size_of::<dc_hashelem_t>() as libc::c_ulong as libc::c_long)
|
||||
as *mut dc_hashelem_t;
|
||||
if new_elem.is_null() {
|
||||
return data;
|
||||
}
|
||||
if 0 != (*pH).copyKey as libc::c_int && !pKey.is_null() {
|
||||
(*new_elem).pKey = malloc(nKey as libc::c_ulong);
|
||||
if (*new_elem).pKey.is_null() {
|
||||
free(new_elem as *mut libc::c_void);
|
||||
return data;
|
||||
}
|
||||
memcpy(
|
||||
(*new_elem).pKey as *mut libc::c_void,
|
||||
pKey,
|
||||
nKey as libc::c_ulong,
|
||||
);
|
||||
} else {
|
||||
(*new_elem).pKey = pKey as *mut libc::c_void
|
||||
}
|
||||
(*new_elem).nKey = nKey;
|
||||
(*pH).count += 1;
|
||||
if (*pH).htsize == 0i32 {
|
||||
rehash(pH, 8i32);
|
||||
if (*pH).htsize == 0i32 {
|
||||
(*pH).count = 0i32;
|
||||
free(new_elem as *mut libc::c_void);
|
||||
return data;
|
||||
}
|
||||
}
|
||||
if (*pH).count > (*pH).htsize {
|
||||
rehash(pH, (*pH).htsize * 2i32);
|
||||
}
|
||||
if 0 != !((*pH).htsize > 0i32) as libc::c_int as libc::c_long {
|
||||
__assert_rtn(
|
||||
(*::std::mem::transmute::<&[u8; 15], &[libc::c_char; 15]>(b"dc_hash_insert\x00"))
|
||||
.as_ptr(),
|
||||
b"../src/dc_hash.c\x00" as *const u8 as *const libc::c_char,
|
||||
491i32,
|
||||
b"pH->htsize>0\x00" as *const u8 as *const libc::c_char,
|
||||
);
|
||||
} else {
|
||||
};
|
||||
if 0 != !((*pH).htsize & (*pH).htsize - 1i32 == 0i32) as libc::c_int as libc::c_long {
|
||||
__assert_rtn(
|
||||
(*::std::mem::transmute::<&[u8; 15], &[libc::c_char; 15]>(b"dc_hash_insert\x00"))
|
||||
.as_ptr(),
|
||||
b"../src/dc_hash.c\x00" as *const u8 as *const libc::c_char,
|
||||
492i32,
|
||||
b"(pH->htsize & (pH->htsize-1))==0\x00" as *const u8 as *const libc::c_char,
|
||||
);
|
||||
} else {
|
||||
};
|
||||
h = hraw & (*pH).htsize - 1i32;
|
||||
insertElement(pH, &mut *(*pH).ht.offset(h as isize), new_elem);
|
||||
(*new_elem).data = data;
|
||||
return 0 as *mut libc::c_void;
|
||||
}
|
||||
/* Link an element into the hash table
|
||||
*/
|
||||
unsafe extern "C" fn insertElement(
|
||||
mut pH: *mut dc_hash_t,
|
||||
mut pEntry: *mut _ht,
|
||||
mut pNew: *mut dc_hashelem_t,
|
||||
) {
|
||||
/* First element already in pEntry */
|
||||
let mut pHead: *mut dc_hashelem_t = 0 as *mut dc_hashelem_t;
|
||||
pHead = (*pEntry).chain;
|
||||
if !pHead.is_null() {
|
||||
(*pNew).next = pHead;
|
||||
(*pNew).prev = (*pHead).prev;
|
||||
if !(*pHead).prev.is_null() {
|
||||
(*(*pHead).prev).next = pNew
|
||||
} else {
|
||||
(*pH).first = pNew
|
||||
}
|
||||
(*pHead).prev = pNew
|
||||
} else {
|
||||
(*pNew).next = (*pH).first;
|
||||
if !(*pH).first.is_null() {
|
||||
(*(*pH).first).prev = pNew
|
||||
}
|
||||
(*pNew).prev = 0 as *mut dc_hashelem_t;
|
||||
(*pH).first = pNew
|
||||
}
|
||||
(*pEntry).count += 1;
|
||||
(*pEntry).chain = pNew;
|
||||
}
|
||||
/* Resize the hash table so that it cantains "new_size" buckets.
|
||||
* "new_size" must be a power of 2. The hash table might fail
|
||||
* to resize if sjhashMalloc() fails.
|
||||
*/
|
||||
unsafe extern "C" fn rehash(mut pH: *mut dc_hash_t, mut new_size: libc::c_int) {
|
||||
/* The new hash table */
|
||||
let mut new_ht: *mut _ht = 0 as *mut _ht;
|
||||
/* For looping over existing elements */
|
||||
let mut elem: *mut dc_hashelem_t = 0 as *mut dc_hashelem_t;
|
||||
let mut next_elem: *mut dc_hashelem_t = 0 as *mut dc_hashelem_t;
|
||||
/* The hash function */
|
||||
let mut xHash: Option<
|
||||
unsafe extern "C" fn(_: *const libc::c_void, _: libc::c_int) -> libc::c_int,
|
||||
> = None;
|
||||
if 0 != !(new_size & new_size - 1i32 == 0i32) as libc::c_int as libc::c_long {
|
||||
__assert_rtn(
|
||||
(*::std::mem::transmute::<&[u8; 7], &[libc::c_char; 7]>(b"rehash\x00")).as_ptr(),
|
||||
b"../src/dc_hash.c\x00" as *const u8 as *const libc::c_char,
|
||||
287i32,
|
||||
b"(new_size & (new_size-1))==0\x00" as *const u8 as *const libc::c_char,
|
||||
);
|
||||
} else {
|
||||
};
|
||||
new_ht = sjhashMalloc(
|
||||
(new_size as libc::c_ulong).wrapping_mul(::std::mem::size_of::<_ht>() as libc::c_ulong)
|
||||
as libc::c_long,
|
||||
) as *mut _ht;
|
||||
if new_ht.is_null() {
|
||||
return;
|
||||
}
|
||||
if !(*pH).ht.is_null() {
|
||||
free((*pH).ht as *mut libc::c_void);
|
||||
}
|
||||
(*pH).ht = new_ht;
|
||||
(*pH).htsize = new_size;
|
||||
xHash = hashFunction((*pH).keyClass as libc::c_int);
|
||||
elem = (*pH).first;
|
||||
(*pH).first = 0 as *mut dc_hashelem_t;
|
||||
while !elem.is_null() {
|
||||
let mut h: libc::c_int =
|
||||
xHash.expect("non-null function pointer")((*elem).pKey, (*elem).nKey) & new_size - 1i32;
|
||||
next_elem = (*elem).next;
|
||||
insertElement(pH, &mut *new_ht.offset(h as isize), elem);
|
||||
elem = next_elem
|
||||
}
|
||||
}
|
||||
/* Return a pointer to the appropriate hash function given the key class.
|
||||
*
|
||||
* About the syntax:
|
||||
* The name of the function is "hashFunction". The function takes a
|
||||
* single parameter "keyClass". The return value of hashFunction()
|
||||
* is a pointer to another function. Specifically, the return value
|
||||
* of hashFunction() is a pointer to a function that takes two parameters
|
||||
* with types "const void*" and "int" and returns an "int".
|
||||
*/
|
||||
unsafe extern "C" fn hashFunction(
|
||||
mut keyClass: libc::c_int,
|
||||
) -> Option<unsafe extern "C" fn(_: *const libc::c_void, _: libc::c_int) -> libc::c_int> {
|
||||
match keyClass {
|
||||
1 => return Some(intHash),
|
||||
2 => return Some(ptrHash),
|
||||
3 => return Some(strHash),
|
||||
4 => return Some(binHash),
|
||||
_ => {}
|
||||
}
|
||||
return None;
|
||||
}
|
||||
/* Hash and comparison functions when the mode is SJHASH_BINARY
|
||||
*/
|
||||
unsafe extern "C" fn binHash(mut pKey: *const libc::c_void, mut nKey: libc::c_int) -> libc::c_int {
|
||||
let mut h: libc::c_int = 0i32;
|
||||
let mut z: *const libc::c_char = pKey as *const libc::c_char;
|
||||
loop {
|
||||
let fresh0 = nKey;
|
||||
nKey = nKey - 1;
|
||||
if !(fresh0 > 0i32) {
|
||||
break;
|
||||
}
|
||||
let fresh1 = z;
|
||||
z = z.offset(1);
|
||||
h = h << 3i32 ^ h ^ *fresh1 as libc::c_int
|
||||
}
|
||||
return h & 0x7fffffffi32;
|
||||
}
|
||||
/* Hash and comparison functions when the mode is SJHASH_STRING
|
||||
*/
|
||||
unsafe extern "C" fn strHash(mut pKey: *const libc::c_void, mut nKey: libc::c_int) -> libc::c_int {
|
||||
return sjhashNoCase(pKey as *const libc::c_char, nKey);
|
||||
}
|
||||
/* This function computes a hash on the name of a keyword.
|
||||
* Case is not significant.
|
||||
*/
|
||||
unsafe extern "C" fn sjhashNoCase(mut z: *const libc::c_char, mut n: libc::c_int) -> libc::c_int {
|
||||
let mut h: libc::c_int = 0i32;
|
||||
if n <= 0i32 {
|
||||
n = strlen(z) as libc::c_int
|
||||
}
|
||||
while n > 0i32 {
|
||||
let fresh2 = z;
|
||||
z = z.offset(1);
|
||||
h = h << 3i32 ^ h ^ sjhashUpperToLower[*fresh2 as libc::c_uchar as usize] as libc::c_int;
|
||||
n -= 1
|
||||
}
|
||||
return h & 0x7fffffffi32;
|
||||
}
|
||||
/* An array to map all upper-case characters into their corresponding
|
||||
* lower-case character.
|
||||
*/
|
||||
static mut sjhashUpperToLower: [libc::c_uchar; 256] = [
|
||||
0i32 as libc::c_uchar,
|
||||
1i32 as libc::c_uchar,
|
||||
2i32 as libc::c_uchar,
|
||||
3i32 as libc::c_uchar,
|
||||
4i32 as libc::c_uchar,
|
||||
5i32 as libc::c_uchar,
|
||||
6i32 as libc::c_uchar,
|
||||
7i32 as libc::c_uchar,
|
||||
8i32 as libc::c_uchar,
|
||||
9i32 as libc::c_uchar,
|
||||
10i32 as libc::c_uchar,
|
||||
11i32 as libc::c_uchar,
|
||||
12i32 as libc::c_uchar,
|
||||
13i32 as libc::c_uchar,
|
||||
14i32 as libc::c_uchar,
|
||||
15i32 as libc::c_uchar,
|
||||
16i32 as libc::c_uchar,
|
||||
17i32 as libc::c_uchar,
|
||||
18i32 as libc::c_uchar,
|
||||
19i32 as libc::c_uchar,
|
||||
20i32 as libc::c_uchar,
|
||||
21i32 as libc::c_uchar,
|
||||
22i32 as libc::c_uchar,
|
||||
23i32 as libc::c_uchar,
|
||||
24i32 as libc::c_uchar,
|
||||
25i32 as libc::c_uchar,
|
||||
26i32 as libc::c_uchar,
|
||||
27i32 as libc::c_uchar,
|
||||
28i32 as libc::c_uchar,
|
||||
29i32 as libc::c_uchar,
|
||||
30i32 as libc::c_uchar,
|
||||
31i32 as libc::c_uchar,
|
||||
32i32 as libc::c_uchar,
|
||||
33i32 as libc::c_uchar,
|
||||
34i32 as libc::c_uchar,
|
||||
35i32 as libc::c_uchar,
|
||||
36i32 as libc::c_uchar,
|
||||
37i32 as libc::c_uchar,
|
||||
38i32 as libc::c_uchar,
|
||||
39i32 as libc::c_uchar,
|
||||
40i32 as libc::c_uchar,
|
||||
41i32 as libc::c_uchar,
|
||||
42i32 as libc::c_uchar,
|
||||
43i32 as libc::c_uchar,
|
||||
44i32 as libc::c_uchar,
|
||||
45i32 as libc::c_uchar,
|
||||
46i32 as libc::c_uchar,
|
||||
47i32 as libc::c_uchar,
|
||||
48i32 as libc::c_uchar,
|
||||
49i32 as libc::c_uchar,
|
||||
50i32 as libc::c_uchar,
|
||||
51i32 as libc::c_uchar,
|
||||
52i32 as libc::c_uchar,
|
||||
53i32 as libc::c_uchar,
|
||||
54i32 as libc::c_uchar,
|
||||
55i32 as libc::c_uchar,
|
||||
56i32 as libc::c_uchar,
|
||||
57i32 as libc::c_uchar,
|
||||
58i32 as libc::c_uchar,
|
||||
59i32 as libc::c_uchar,
|
||||
60i32 as libc::c_uchar,
|
||||
61i32 as libc::c_uchar,
|
||||
62i32 as libc::c_uchar,
|
||||
63i32 as libc::c_uchar,
|
||||
64i32 as libc::c_uchar,
|
||||
97i32 as libc::c_uchar,
|
||||
98i32 as libc::c_uchar,
|
||||
99i32 as libc::c_uchar,
|
||||
100i32 as libc::c_uchar,
|
||||
101i32 as libc::c_uchar,
|
||||
102i32 as libc::c_uchar,
|
||||
103i32 as libc::c_uchar,
|
||||
104i32 as libc::c_uchar,
|
||||
105i32 as libc::c_uchar,
|
||||
106i32 as libc::c_uchar,
|
||||
107i32 as libc::c_uchar,
|
||||
108i32 as libc::c_uchar,
|
||||
109i32 as libc::c_uchar,
|
||||
110i32 as libc::c_uchar,
|
||||
111i32 as libc::c_uchar,
|
||||
112i32 as libc::c_uchar,
|
||||
113i32 as libc::c_uchar,
|
||||
114i32 as libc::c_uchar,
|
||||
115i32 as libc::c_uchar,
|
||||
116i32 as libc::c_uchar,
|
||||
117i32 as libc::c_uchar,
|
||||
118i32 as libc::c_uchar,
|
||||
119i32 as libc::c_uchar,
|
||||
120i32 as libc::c_uchar,
|
||||
121i32 as libc::c_uchar,
|
||||
122i32 as libc::c_uchar,
|
||||
91i32 as libc::c_uchar,
|
||||
92i32 as libc::c_uchar,
|
||||
93i32 as libc::c_uchar,
|
||||
94i32 as libc::c_uchar,
|
||||
95i32 as libc::c_uchar,
|
||||
96i32 as libc::c_uchar,
|
||||
97i32 as libc::c_uchar,
|
||||
98i32 as libc::c_uchar,
|
||||
99i32 as libc::c_uchar,
|
||||
100i32 as libc::c_uchar,
|
||||
101i32 as libc::c_uchar,
|
||||
102i32 as libc::c_uchar,
|
||||
103i32 as libc::c_uchar,
|
||||
104i32 as libc::c_uchar,
|
||||
105i32 as libc::c_uchar,
|
||||
106i32 as libc::c_uchar,
|
||||
107i32 as libc::c_uchar,
|
||||
108i32 as libc::c_uchar,
|
||||
109i32 as libc::c_uchar,
|
||||
110i32 as libc::c_uchar,
|
||||
111i32 as libc::c_uchar,
|
||||
112i32 as libc::c_uchar,
|
||||
113i32 as libc::c_uchar,
|
||||
114i32 as libc::c_uchar,
|
||||
115i32 as libc::c_uchar,
|
||||
116i32 as libc::c_uchar,
|
||||
117i32 as libc::c_uchar,
|
||||
118i32 as libc::c_uchar,
|
||||
119i32 as libc::c_uchar,
|
||||
120i32 as libc::c_uchar,
|
||||
121i32 as libc::c_uchar,
|
||||
122i32 as libc::c_uchar,
|
||||
123i32 as libc::c_uchar,
|
||||
124i32 as libc::c_uchar,
|
||||
125i32 as libc::c_uchar,
|
||||
126i32 as libc::c_uchar,
|
||||
127i32 as libc::c_uchar,
|
||||
128i32 as libc::c_uchar,
|
||||
129i32 as libc::c_uchar,
|
||||
130i32 as libc::c_uchar,
|
||||
131i32 as libc::c_uchar,
|
||||
132i32 as libc::c_uchar,
|
||||
133i32 as libc::c_uchar,
|
||||
134i32 as libc::c_uchar,
|
||||
135i32 as libc::c_uchar,
|
||||
136i32 as libc::c_uchar,
|
||||
137i32 as libc::c_uchar,
|
||||
138i32 as libc::c_uchar,
|
||||
139i32 as libc::c_uchar,
|
||||
140i32 as libc::c_uchar,
|
||||
141i32 as libc::c_uchar,
|
||||
142i32 as libc::c_uchar,
|
||||
143i32 as libc::c_uchar,
|
||||
144i32 as libc::c_uchar,
|
||||
145i32 as libc::c_uchar,
|
||||
146i32 as libc::c_uchar,
|
||||
147i32 as libc::c_uchar,
|
||||
148i32 as libc::c_uchar,
|
||||
149i32 as libc::c_uchar,
|
||||
150i32 as libc::c_uchar,
|
||||
151i32 as libc::c_uchar,
|
||||
152i32 as libc::c_uchar,
|
||||
153i32 as libc::c_uchar,
|
||||
154i32 as libc::c_uchar,
|
||||
155i32 as libc::c_uchar,
|
||||
156i32 as libc::c_uchar,
|
||||
157i32 as libc::c_uchar,
|
||||
158i32 as libc::c_uchar,
|
||||
159i32 as libc::c_uchar,
|
||||
160i32 as libc::c_uchar,
|
||||
161i32 as libc::c_uchar,
|
||||
162i32 as libc::c_uchar,
|
||||
163i32 as libc::c_uchar,
|
||||
164i32 as libc::c_uchar,
|
||||
165i32 as libc::c_uchar,
|
||||
166i32 as libc::c_uchar,
|
||||
167i32 as libc::c_uchar,
|
||||
168i32 as libc::c_uchar,
|
||||
169i32 as libc::c_uchar,
|
||||
170i32 as libc::c_uchar,
|
||||
171i32 as libc::c_uchar,
|
||||
172i32 as libc::c_uchar,
|
||||
173i32 as libc::c_uchar,
|
||||
174i32 as libc::c_uchar,
|
||||
175i32 as libc::c_uchar,
|
||||
176i32 as libc::c_uchar,
|
||||
177i32 as libc::c_uchar,
|
||||
178i32 as libc::c_uchar,
|
||||
179i32 as libc::c_uchar,
|
||||
180i32 as libc::c_uchar,
|
||||
181i32 as libc::c_uchar,
|
||||
182i32 as libc::c_uchar,
|
||||
183i32 as libc::c_uchar,
|
||||
184i32 as libc::c_uchar,
|
||||
185i32 as libc::c_uchar,
|
||||
186i32 as libc::c_uchar,
|
||||
187i32 as libc::c_uchar,
|
||||
188i32 as libc::c_uchar,
|
||||
189i32 as libc::c_uchar,
|
||||
190i32 as libc::c_uchar,
|
||||
191i32 as libc::c_uchar,
|
||||
192i32 as libc::c_uchar,
|
||||
193i32 as libc::c_uchar,
|
||||
194i32 as libc::c_uchar,
|
||||
195i32 as libc::c_uchar,
|
||||
196i32 as libc::c_uchar,
|
||||
197i32 as libc::c_uchar,
|
||||
198i32 as libc::c_uchar,
|
||||
199i32 as libc::c_uchar,
|
||||
200i32 as libc::c_uchar,
|
||||
201i32 as libc::c_uchar,
|
||||
202i32 as libc::c_uchar,
|
||||
203i32 as libc::c_uchar,
|
||||
204i32 as libc::c_uchar,
|
||||
205i32 as libc::c_uchar,
|
||||
206i32 as libc::c_uchar,
|
||||
207i32 as libc::c_uchar,
|
||||
208i32 as libc::c_uchar,
|
||||
209i32 as libc::c_uchar,
|
||||
210i32 as libc::c_uchar,
|
||||
211i32 as libc::c_uchar,
|
||||
212i32 as libc::c_uchar,
|
||||
213i32 as libc::c_uchar,
|
||||
214i32 as libc::c_uchar,
|
||||
215i32 as libc::c_uchar,
|
||||
216i32 as libc::c_uchar,
|
||||
217i32 as libc::c_uchar,
|
||||
218i32 as libc::c_uchar,
|
||||
219i32 as libc::c_uchar,
|
||||
220i32 as libc::c_uchar,
|
||||
221i32 as libc::c_uchar,
|
||||
222i32 as libc::c_uchar,
|
||||
223i32 as libc::c_uchar,
|
||||
224i32 as libc::c_uchar,
|
||||
225i32 as libc::c_uchar,
|
||||
226i32 as libc::c_uchar,
|
||||
227i32 as libc::c_uchar,
|
||||
228i32 as libc::c_uchar,
|
||||
229i32 as libc::c_uchar,
|
||||
230i32 as libc::c_uchar,
|
||||
231i32 as libc::c_uchar,
|
||||
232i32 as libc::c_uchar,
|
||||
233i32 as libc::c_uchar,
|
||||
234i32 as libc::c_uchar,
|
||||
235i32 as libc::c_uchar,
|
||||
236i32 as libc::c_uchar,
|
||||
237i32 as libc::c_uchar,
|
||||
238i32 as libc::c_uchar,
|
||||
239i32 as libc::c_uchar,
|
||||
240i32 as libc::c_uchar,
|
||||
241i32 as libc::c_uchar,
|
||||
242i32 as libc::c_uchar,
|
||||
243i32 as libc::c_uchar,
|
||||
244i32 as libc::c_uchar,
|
||||
245i32 as libc::c_uchar,
|
||||
246i32 as libc::c_uchar,
|
||||
247i32 as libc::c_uchar,
|
||||
248i32 as libc::c_uchar,
|
||||
249i32 as libc::c_uchar,
|
||||
250i32 as libc::c_uchar,
|
||||
251i32 as libc::c_uchar,
|
||||
252i32 as libc::c_uchar,
|
||||
253i32 as libc::c_uchar,
|
||||
254i32 as libc::c_uchar,
|
||||
255i32 as libc::c_uchar,
|
||||
];
|
||||
/* Hash and comparison functions when the mode is SJHASH_POINTER
|
||||
*/
|
||||
unsafe extern "C" fn ptrHash(mut pKey: *const libc::c_void, mut nKey: libc::c_int) -> libc::c_int {
|
||||
let mut x: uintptr_t = pKey as uintptr_t;
|
||||
return (x ^ x << 8i32 ^ x >> 8i32) as libc::c_int;
|
||||
}
|
||||
/* Hash and comparison functions when the mode is SJHASH_INT
|
||||
*/
|
||||
unsafe extern "C" fn intHash(mut pKey: *const libc::c_void, mut nKey: libc::c_int) -> libc::c_int {
|
||||
return nKey ^ nKey << 8i32 ^ nKey >> 8i32;
|
||||
}
|
||||
/*
|
||||
** Based upon hash.c from sqlite which author disclaims copyright to this source code. In place of
|
||||
** a legal notice, here is a blessing:
|
||||
**
|
||||
** May you do good and not evil.
|
||||
** May you find forgiveness for yourself and forgive others.
|
||||
** May you share freely, never taking more than you give.
|
||||
*/
|
||||
unsafe extern "C" fn sjhashMalloc(mut bytes: libc::c_long) -> *mut libc::c_void {
|
||||
let mut p: *mut libc::c_void = malloc(bytes as libc::c_ulong);
|
||||
if !p.is_null() {
|
||||
memset(p, 0i32, bytes as libc::c_ulong);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
/* Remove a single entry from the hash table given a pointer to that
|
||||
* element and a hash on the element's key.
|
||||
*/
|
||||
unsafe extern "C" fn removeElementGivenHash(
|
||||
mut pH: *mut dc_hash_t,
|
||||
mut elem: *mut dc_hashelem_t,
|
||||
mut h: libc::c_int,
|
||||
) {
|
||||
let mut pEntry: *mut _ht = 0 as *mut _ht;
|
||||
if !(*elem).prev.is_null() {
|
||||
(*(*elem).prev).next = (*elem).next
|
||||
} else {
|
||||
(*pH).first = (*elem).next
|
||||
}
|
||||
if !(*elem).next.is_null() {
|
||||
(*(*elem).next).prev = (*elem).prev
|
||||
}
|
||||
pEntry = &mut *(*pH).ht.offset(h as isize) as *mut _ht;
|
||||
if (*pEntry).chain == elem {
|
||||
(*pEntry).chain = (*elem).next
|
||||
}
|
||||
(*pEntry).count -= 1;
|
||||
if (*pEntry).count <= 0i32 {
|
||||
(*pEntry).chain = 0 as *mut dc_hashelem_t
|
||||
}
|
||||
if 0 != (*pH).copyKey as libc::c_int && !(*elem).pKey.is_null() {
|
||||
free((*elem).pKey);
|
||||
}
|
||||
free(elem as *mut libc::c_void);
|
||||
(*pH).count -= 1;
|
||||
}
|
||||
/* This function (for internal use only) locates an element in an
|
||||
* hash table that matches the given key. The hash for this key has
|
||||
* already been computed and is passed as the 4th parameter.
|
||||
*/
|
||||
unsafe extern "C" fn findElementGivenHash(
|
||||
mut pH: *const dc_hash_t,
|
||||
mut pKey: *const libc::c_void,
|
||||
mut nKey: libc::c_int,
|
||||
mut h: libc::c_int,
|
||||
) -> *mut dc_hashelem_t {
|
||||
/* Used to loop thru the element list */
|
||||
let mut elem: *mut dc_hashelem_t = 0 as *mut dc_hashelem_t;
|
||||
/* Number of elements left to test */
|
||||
let mut count: libc::c_int = 0;
|
||||
/* comparison function */
|
||||
let mut xCompare: Option<
|
||||
unsafe extern "C" fn(
|
||||
_: *const libc::c_void,
|
||||
_: libc::c_int,
|
||||
_: *const libc::c_void,
|
||||
_: libc::c_int,
|
||||
) -> libc::c_int,
|
||||
> = None;
|
||||
if !(*pH).ht.is_null() {
|
||||
let mut pEntry: *mut _ht = &mut *(*pH).ht.offset(h as isize) as *mut _ht;
|
||||
elem = (*pEntry).chain;
|
||||
count = (*pEntry).count;
|
||||
xCompare = compareFunction((*pH).keyClass as libc::c_int);
|
||||
loop {
|
||||
let fresh3 = count;
|
||||
count = count - 1;
|
||||
if !(0 != fresh3 && !elem.is_null()) {
|
||||
break;
|
||||
}
|
||||
if xCompare.expect("non-null function pointer")((*elem).pKey, (*elem).nKey, pKey, nKey)
|
||||
== 0i32
|
||||
{
|
||||
return elem;
|
||||
}
|
||||
elem = (*elem).next
|
||||
}
|
||||
}
|
||||
return 0 as *mut dc_hashelem_t;
|
||||
}
|
||||
/* Return a pointer to the appropriate hash function given the key class.
|
||||
*/
|
||||
unsafe extern "C" fn compareFunction(
|
||||
mut keyClass: libc::c_int,
|
||||
) -> Option<
|
||||
unsafe extern "C" fn(
|
||||
_: *const libc::c_void,
|
||||
_: libc::c_int,
|
||||
_: *const libc::c_void,
|
||||
_: libc::c_int,
|
||||
) -> libc::c_int,
|
||||
> {
|
||||
match keyClass {
|
||||
1 => return Some(intCompare),
|
||||
2 => return Some(ptrCompare),
|
||||
3 => return Some(strCompare),
|
||||
4 => return Some(binCompare),
|
||||
_ => {}
|
||||
}
|
||||
return None;
|
||||
}
|
||||
unsafe extern "C" fn binCompare(
|
||||
mut pKey1: *const libc::c_void,
|
||||
mut n1: libc::c_int,
|
||||
mut pKey2: *const libc::c_void,
|
||||
mut n2: libc::c_int,
|
||||
) -> libc::c_int {
|
||||
if n1 != n2 {
|
||||
return 1i32;
|
||||
}
|
||||
return memcmp(pKey1, pKey2, n1 as libc::c_ulong);
|
||||
}
|
||||
unsafe extern "C" fn strCompare(
|
||||
mut pKey1: *const libc::c_void,
|
||||
mut n1: libc::c_int,
|
||||
mut pKey2: *const libc::c_void,
|
||||
mut n2: libc::c_int,
|
||||
) -> libc::c_int {
|
||||
if n1 != n2 {
|
||||
return 1i32;
|
||||
}
|
||||
return sjhashStrNICmp(
|
||||
pKey1 as *const libc::c_char,
|
||||
pKey2 as *const libc::c_char,
|
||||
n1,
|
||||
);
|
||||
}
|
||||
/* Some systems have stricmp(). Others have strcasecmp(). Because
|
||||
* there is no consistency, we will define our own.
|
||||
*/
|
||||
unsafe extern "C" fn sjhashStrNICmp(
|
||||
mut zLeft: *const libc::c_char,
|
||||
mut zRight: *const libc::c_char,
|
||||
mut N: libc::c_int,
|
||||
) -> libc::c_int {
|
||||
let mut a: *mut libc::c_uchar = 0 as *mut libc::c_uchar;
|
||||
let mut b: *mut libc::c_uchar = 0 as *mut libc::c_uchar;
|
||||
a = zLeft as *mut libc::c_uchar;
|
||||
b = zRight as *mut libc::c_uchar;
|
||||
loop {
|
||||
let fresh4 = N;
|
||||
N = N - 1;
|
||||
if !(fresh4 > 0i32
|
||||
&& *a as libc::c_int != 0i32
|
||||
&& sjhashUpperToLower[*a as usize] as libc::c_int
|
||||
== sjhashUpperToLower[*b as usize] as libc::c_int)
|
||||
{
|
||||
break;
|
||||
}
|
||||
a = a.offset(1isize);
|
||||
b = b.offset(1isize)
|
||||
}
|
||||
return if N < 0i32 {
|
||||
0i32
|
||||
} else {
|
||||
sjhashUpperToLower[*a as usize] as libc::c_int
|
||||
- sjhashUpperToLower[*b as usize] as libc::c_int
|
||||
};
|
||||
}
|
||||
unsafe extern "C" fn ptrCompare(
|
||||
mut pKey1: *const libc::c_void,
|
||||
mut n1: libc::c_int,
|
||||
mut pKey2: *const libc::c_void,
|
||||
mut n2: libc::c_int,
|
||||
) -> libc::c_int {
|
||||
if pKey1 == pKey2 {
|
||||
return 0i32;
|
||||
}
|
||||
if pKey1 < pKey2 {
|
||||
return -1i32;
|
||||
}
|
||||
return 1i32;
|
||||
}
|
||||
unsafe extern "C" fn intCompare(
|
||||
mut pKey1: *const libc::c_void,
|
||||
mut n1: libc::c_int,
|
||||
mut pKey2: *const libc::c_void,
|
||||
mut n2: libc::c_int,
|
||||
) -> libc::c_int {
|
||||
return n2 - n1;
|
||||
}
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_hash_find(
|
||||
mut pH: *const dc_hash_t,
|
||||
mut pKey: *const libc::c_void,
|
||||
mut nKey: libc::c_int,
|
||||
) -> *mut libc::c_void {
|
||||
/* A hash on key */
|
||||
let mut h: libc::c_int = 0;
|
||||
/* The element that matches key */
|
||||
let mut elem: *mut dc_hashelem_t = 0 as *mut dc_hashelem_t;
|
||||
/* The hash function */
|
||||
let mut xHash: Option<
|
||||
unsafe extern "C" fn(_: *const libc::c_void, _: libc::c_int) -> libc::c_int,
|
||||
> = None;
|
||||
if pH.is_null() || (*pH).ht.is_null() {
|
||||
return 0 as *mut libc::c_void;
|
||||
}
|
||||
xHash = hashFunction((*pH).keyClass as libc::c_int);
|
||||
if 0 != xHash.is_none() as libc::c_int as libc::c_long {
|
||||
__assert_rtn(
|
||||
(*::std::mem::transmute::<&[u8; 13], &[libc::c_char; 13]>(b"dc_hash_find\x00"))
|
||||
.as_ptr(),
|
||||
b"../src/dc_hash.c\x00" as *const u8 as *const libc::c_char,
|
||||
397i32,
|
||||
b"xHash!=0\x00" as *const u8 as *const libc::c_char,
|
||||
);
|
||||
} else {
|
||||
};
|
||||
h = xHash.expect("non-null function pointer")(pKey, nKey);
|
||||
if 0 != !((*pH).htsize & (*pH).htsize - 1i32 == 0i32) as libc::c_int as libc::c_long {
|
||||
__assert_rtn(
|
||||
(*::std::mem::transmute::<&[u8; 13], &[libc::c_char; 13]>(b"dc_hash_find\x00"))
|
||||
.as_ptr(),
|
||||
b"../src/dc_hash.c\x00" as *const u8 as *const libc::c_char,
|
||||
399i32,
|
||||
b"(pH->htsize & (pH->htsize-1))==0\x00" as *const u8 as *const libc::c_char,
|
||||
);
|
||||
} else {
|
||||
};
|
||||
elem = findElementGivenHash(pH, pKey, nKey, h & (*pH).htsize - 1i32);
|
||||
return if !elem.is_null() {
|
||||
(*elem).data
|
||||
} else {
|
||||
0 as *mut libc::c_void
|
||||
};
|
||||
}
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dc_hash_clear(mut pH: *mut dc_hash_t) {
|
||||
/* For looping over all elements of the table */
|
||||
let mut elem: *mut dc_hashelem_t = 0 as *mut dc_hashelem_t;
|
||||
if pH.is_null() {
|
||||
return;
|
||||
}
|
||||
elem = (*pH).first;
|
||||
(*pH).first = 0 as *mut dc_hashelem_t;
|
||||
if !(*pH).ht.is_null() {
|
||||
free((*pH).ht as *mut libc::c_void);
|
||||
}
|
||||
(*pH).ht = 0 as *mut _ht;
|
||||
(*pH).htsize = 0i32;
|
||||
while !elem.is_null() {
|
||||
let mut next_elem: *mut dc_hashelem_t = (*elem).next;
|
||||
if 0 != (*pH).copyKey as libc::c_int && !(*elem).pKey.is_null() {
|
||||
free((*elem).pKey);
|
||||
}
|
||||
free(elem as *mut libc::c_void);
|
||||
elem = next_elem
|
||||
}
|
||||
(*pH).count = 0i32;
|
||||
}
|
||||
Reference in New Issue
Block a user