15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
16 |
16 |
17 #include "cdb++.h" |
17 #include "cdb++.h" |
18 #include "internal.h" |
18 #include "internal.h" |
19 |
19 |
20 static int match(fdibuf& in, const mystring& key) |
20 char* cdb_reader::seek(const mystring& key, uint32& dlen) |
21 { |
|
22 unsigned len = key.length(); |
|
23 const char* keyptr = key.c_str(); |
|
24 |
|
25 while (len > 0) { |
|
26 char buf[32]; |
|
27 unsigned n = sizeof buf; |
|
28 if(n > len) n = len; |
|
29 if(!in.read(buf, n)) return -1; |
|
30 for(unsigned i = 0;i < n;++i) |
|
31 if(buf[i] != keyptr[i]) return 0; |
|
32 keyptr += n; |
|
33 len -= n; |
|
34 } |
|
35 return 1; |
|
36 } |
|
37 |
|
38 int cdb_reader::seek(const mystring& key, uint32& dlen) |
|
39 { |
21 { |
40 if(failed) |
22 if(failed) |
41 return -1; |
23 return 0; |
42 uint32 h = hash(key); |
24 uint32 h = hash(key); |
43 uint32 pos = 8 * (h & 255); |
25 uint32 pos = 8 * (h & 255); |
44 |
26 |
45 uint32 poshash = unpack(header+pos); |
27 uint32 poshash = unpack(map+pos); |
46 uint32 lenhash = unpack(header+pos+4); |
28 uint32 lenhash = unpack(map+pos+4); |
47 |
29 |
48 if(!lenhash) return 0; |
30 if(!lenhash) |
|
31 return 0; |
49 uint32 h2 = (h >> 8) % lenhash; |
32 uint32 h2 = (h >> 8) % lenhash; |
50 |
33 |
51 for (uint32 loop = 0; loop < lenhash; ++loop) { |
34 for (uint32 loop = 0; loop < lenhash; ++loop) { |
52 if(!in.seek(poshash+8*h2)) return -1; |
35 unsigned char* ptrhash = map + poshash + 8*h2; |
53 unsigned char packbuf[8]; |
36 uint32 poskd = unpack(ptrhash + 4); |
54 if(!in.read(packbuf, 8)) return -1; |
37 if(!poskd) |
55 uint32 poskd = unpack(packbuf + 4); |
38 return 0; |
56 if(!poskd) return 0; |
39 if(unpack(ptrhash) == h) { |
57 if(unpack(packbuf) == h) { |
40 unsigned char* ptrmatch = map + poskd; |
58 if(!in.seek(poskd)) return -1; |
41 if(unpack(ptrmatch) == key.length() && |
59 if(!in.read(packbuf, 8)) return -1; |
42 !memcmp(ptrmatch+8, key.c_str(), key.length())) { |
60 if(unpack(packbuf) == key.length()) |
43 dlen = unpack(ptrmatch + 4); |
61 switch(match(in, key)) { |
44 return (char*)ptrmatch + 8 + key.length(); |
62 case -1: |
45 } |
63 return -1; |
|
64 case 1: |
|
65 dlen = unpack(packbuf + 4); |
|
66 return 1; |
|
67 } |
|
68 } |
46 } |
69 if(++h2 == lenhash) h2 = 0; |
47 if(++h2 == lenhash) h2 = 0; |
70 } |
48 } |
71 return 0; |
49 return 0; |
72 } |
50 } |
73 |
51 |
74 datum* cdb_reader::get(const mystring& key) |
52 datum* cdb_reader::get(const mystring& key) |
75 { |
53 { |
76 if(failed) |
54 if(failed) |
77 return 0; |
55 return 0; |
78 uint32 len; |
56 uint32 datalen; |
79 switch(seek(key, len)) { |
57 char* dataptr = seek(key, datalen); |
80 case -1: return 0; |
58 if(!dataptr) |
81 case 0: return 0; |
59 return 0; |
82 } |
60 return new datum(key, mystring(dataptr, datalen)); |
83 // Big assume: data is relatively small (will fit on stack) |
|
84 char buf[len]; |
|
85 datum* d = !in.read(buf, len) ? 0 : new datum(key, mystring(buf, len)); |
|
86 return d; |
|
87 } |
61 } |