12 // |
12 // |
13 // You should have received a copy of the GNU General Public License |
13 // You should have received a copy of the GNU General Public License |
14 // along with this program; if not, write to the Free Software |
14 // along with this program; if not, write to the Free Software |
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 <sys/types.h> |
|
18 #include <sys/stat.h> |
|
19 #include <sys/mman.h> |
|
20 #include <unistd.h> |
17 #include "cdb++.h" |
21 #include "cdb++.h" |
18 #include "internal.h" |
22 #include "internal.h" |
19 |
23 |
20 #define FAIL do{ abort(); return 0; }while(0) |
24 #define FAIL do{ abort(); return 0; }while(0) |
21 |
25 |
23 { |
27 { |
24 return a > b ? a : b; |
28 return a > b ? a : b; |
25 } |
29 } |
26 |
30 |
27 cdb_reader::cdb_reader(const mystring& filename) |
31 cdb_reader::cdb_reader(const mystring& filename) |
28 : in(filename.c_str()), |
32 : map(0), |
29 failed(!in), |
33 failed(1), |
30 eof(false) |
34 eof(false) |
31 { |
35 { |
|
36 int fd = open(filename.c_str(), O_RDONLY); |
|
37 if(fd == -1) return; |
|
38 struct stat buf; |
|
39 if(fstat(fd, &buf) != -1) |
|
40 map = (unsigned char*)mmap(0, buf.st_size, PROT_READ, MAP_SHARED, fd, 0); |
|
41 close(fd); |
|
42 failed = !map; |
32 firstrec(); |
43 firstrec(); |
33 } |
44 } |
34 |
45 |
35 cdb_reader::~cdb_reader() |
46 cdb_reader::~cdb_reader() |
36 { |
47 { |
37 } |
48 } |
38 |
49 |
39 void cdb_reader::abort() |
50 void cdb_reader::abort() |
40 { |
51 { |
41 failed = true; |
52 failed = true; |
42 in.close(); |
53 if(map) |
|
54 munmap(map, size); |
43 } |
55 } |
44 |
56 |
45 bool cdb_reader::firstrec() |
57 bool cdb_reader::firstrec() |
46 { |
58 { |
47 if(failed) return false; |
59 if(failed) return false; |
48 if(!in.seek(0) || !in.read(header, 2048)) { |
60 ptr = map + 2048; |
49 abort(); |
61 eod = map + unpack(map); |
50 return false; |
|
51 } |
|
52 eof = false; |
|
53 eod = unpack(header); |
|
54 pos = 2048; |
|
55 return true; |
62 return true; |
56 } |
63 } |
57 |
64 |
58 datum* cdb_reader::nextrec() |
65 datum* cdb_reader::nextrec() |
59 { |
66 { |
60 if(eof) return 0; |
67 if(eof) return 0; |
61 if(pos >= eod) { |
68 if(ptr >= eod) { |
62 eof = true; |
69 eof = true; |
63 return 0; |
70 return 0; |
64 } |
71 } |
65 if(failed || eod-pos < 8 || !in.seek(pos)) FAIL; |
72 if(failed || eod-ptr < 8) FAIL; |
66 pos += 8; |
73 uint32 klen = unpack(ptr); ptr += 4; |
67 unsigned char buf[8]; |
74 uint32 dlen = unpack(ptr); ptr += 4; |
68 if(!in.read(buf, 8)) FAIL; |
75 if ((uint32)(eod - ptr) < klen + dlen) FAIL; |
69 uint32 klen = unpack(buf); |
76 datum* result = new datum(mystring((char*)ptr, klen), |
70 uint32 dlen = unpack(buf+4); |
77 mystring((char*)ptr+klen, dlen)); |
71 if (eod - pos < klen) FAIL; |
78 ptr += klen + dlen; |
72 pos += klen; |
79 return result; |
73 if (eod - pos < dlen) FAIL; |
|
74 pos += dlen; |
|
75 char tmp[max(klen, dlen)]; |
|
76 if(!in.read(tmp, klen)) FAIL; |
|
77 mystring key(tmp, klen); |
|
78 if(!in.read(tmp, dlen)) FAIL; |
|
79 mystring data(tmp, dlen); |
|
80 return new datum(key, data); |
|
81 } |
80 } |