Branch data Line data Source code
1 : : /* cdb_find.c: cdb_find routine
2 : : *
3 : : * This file is a part of tinycdb package.
4 : : * Copyright (C) 2001-2023 Michael Tokarev <mjt+cdb@corpit.ru>
5 : : *
6 : : * Permission is hereby granted, free of charge, to any person obtaining a
7 : : * copy of this software and associated documentation files (the "Software"),
8 : : * to deal in the Software without restriction, including without limitation
9 : : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 : : * and/or sell copies of the Software, and to permit persons to whom the
11 : : * Software is furnished to do so, subject to the following conditions:
12 : : *
13 : : * The above copyright notice and this permission notice shall be included
14 : : * in all copies or substantial portions of the Software.
15 : : *
16 : : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 : : * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 : : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 : : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 : : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 : : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 : : * DEALINGS IN THE SOFTWARE.
23 : : */
24 : :
25 : : #include "cdb_int.h"
26 : :
27 : : int
28 : 0 : cdb_find(struct cdb *cdbp, const void *key, unsigned klen)
29 : : {
30 : : const unsigned char *htp; /* hash table pointer */
31 : : const unsigned char *htab; /* hash table */
32 : : const unsigned char *htend; /* end of hash table */
33 : : unsigned httodo; /* ht bytes left to look */
34 : : unsigned pos, n;
35 : :
36 : : unsigned hval;
37 : :
38 [ # # ]: 0 : if (klen >= cdbp->cdb_dend) /* if key size is too large */
39 : 0 : return 0;
40 : :
41 : 0 : hval = cdb_hash(key, klen);
42 : :
43 : : /* find (pos,n) hash table to use */
44 : : /* first 2048 bytes (toc) are always available */
45 : : /* (hval % 256) * 8 */
46 : 0 : htp = cdbp->cdb_mem + ((hval << 3) & 2047); /* index in toc (256x8) */
47 : 0 : n = cdb_unpack(htp + 4); /* table size */
48 [ # # ]: 0 : if (!n) /* empty table */
49 : 0 : return 0; /* not found */
50 : 0 : httodo = n << 3; /* bytes of htab to lookup */
51 : 0 : pos = cdb_unpack(htp); /* htab position */
52 [ # # ]: 0 : if (n > (cdbp->cdb_fsize >> 3) /* overflow of httodo ? */
53 [ # # ]: 0 : || pos < cdbp->cdb_dend /* is htab inside data section ? */
54 [ # # ]: 0 : || pos > cdbp->cdb_fsize /* htab start within file ? */
55 [ # # ]: 0 : || httodo > cdbp->cdb_fsize - pos) /* entrie htab within file ? */
56 : 0 : return errno = EPROTO, -1;
57 : :
58 : 0 : htab = cdbp->cdb_mem + pos; /* htab pointer */
59 : 0 : htend = htab + httodo; /* after end of htab */
60 : : /* htab starting position: rest of hval modulo htsize, 8bytes per elt */
61 : 0 : htp = htab + (((hval >> 8) % n) << 3);
62 : :
63 : : for(;;) {
64 : 0 : pos = cdb_unpack(htp + 4); /* record position */
65 [ # # ]: 0 : if (!pos)
66 : 0 : return 0;
67 [ # # ]: 0 : if (cdb_unpack(htp) == hval) {
68 [ # # ]: 0 : if (pos > cdbp->cdb_dend - 8) /* key+val lengths */
69 : 0 : return errno = EPROTO, -1;
70 [ # # ]: 0 : if (cdb_unpack(cdbp->cdb_mem + pos) == klen) {
71 [ # # ]: 0 : if (cdbp->cdb_dend - klen < pos + 8)
72 : 0 : return errno = EPROTO, -1;
73 [ # # ]: 0 : if (memcmp(key, cdbp->cdb_mem + pos + 8, klen) == 0) {
74 : 0 : n = cdb_unpack(cdbp->cdb_mem + pos + 4);
75 : 0 : pos += 8;
76 [ # # # # ]: 0 : if (cdbp->cdb_dend < n || cdbp->cdb_dend - n < pos + klen)
77 : 0 : return errno = EPROTO, -1;
78 : 0 : cdbp->cdb_kpos = pos;
79 : 0 : cdbp->cdb_klen = klen;
80 : 0 : cdbp->cdb_vpos = pos + klen;
81 : 0 : cdbp->cdb_vlen = n;
82 : 0 : return 1;
83 : : }
84 : : }
85 : : }
86 : 0 : httodo -= 8;
87 [ # # ]: 0 : if (!httodo)
88 : 0 : return 0;
89 [ # # ]: 0 : if ((htp += 8) >= htend)
90 : 0 : htp = htab;
91 : : }
92 : :
93 : : }
|