Files
chatmail-core/src/dc_hash.rs
2019-04-28 15:18:30 +03:00

883 lines
28 KiB
Rust

use libc;
use crate::types::*;
use crate::x::*;
/* 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_t {
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,
}
/*
* 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.
*/
pub unsafe 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;
}
pub unsafe 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 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_int) 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 usize);
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 usize);
} else {
(*new_elem).pKey = pKey as *mut libc::c_void
}
(*new_elem).nKey = nKey;
(*pH).count += 1;
if (*pH).htsize == 0i32 {
rehash(pH, 8);
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 * 2);
}
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 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 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.wrapping_mul(::std::mem::size_of::<_ht>() as libc::c_int) as libc::c_int,
) 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 fn hashFunction(
mut keyClass: libc::c_int,
) -> Option<unsafe 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 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 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 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 fn ptrHash(pKey: *const libc::c_void, _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 fn intHash(_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 fn sjhashMalloc(mut bytes: libc::c_int) -> *mut libc::c_void {
let mut p: *mut libc::c_void = malloc(bytes as size_t);
if !p.is_null() {
memset(p, 0i32, bytes as size_t);
}
p
}
/* Remove a single entry from the hash table given a pointer to that
* element and a hash on the element's key.
*/
unsafe 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 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 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 fn compareFunction(
mut keyClass: libc::c_int,
) -> Option<
unsafe 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 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::size_t);
}
unsafe 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 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 fn ptrCompare(
pKey1: *const libc::c_void,
_n1: libc::c_int,
pKey2: *const libc::c_void,
_n2: libc::c_int,
) -> libc::c_int {
if pKey1 == pKey2 {
return 0i32;
}
if pKey1 < pKey2 {
return -1i32;
}
return 1i32;
}
unsafe fn intCompare(
_pKey1: *const libc::c_void,
n1: libc::c_int,
_pKey2: *const libc::c_void,
n2: libc::c_int,
) -> libc::c_int {
return n2 - n1;
}
pub unsafe 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 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 {
__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 {
__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
};
}
pub unsafe 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;
}