Mercurial > hg > cdb
comparison cdb.c @ 0:2cb46628feec
from cdb-0.75 per http://cr.yp.to/cdb.html,
retrieved 2025-01-03,
contents appear to have been create on 2000-02-19
| author | Henry S. Thompson <ht@inf.ed.ac.uk> |
|---|---|
| date | Wed, 29 Jan 2025 10:50:34 +0000 |
| parents | |
| children | 41b9b6a160d1 |
comparison
equal
deleted
inserted
replaced
| -1:000000000000 | 0:2cb46628feec |
|---|---|
| 1 /* Public domain. */ | |
| 2 | |
| 3 #include <sys/types.h> | |
| 4 #include <sys/stat.h> | |
| 5 #include <sys/mman.h> | |
| 6 #include "readwrite.h" | |
| 7 #include "error.h" | |
| 8 #include "seek.h" | |
| 9 #include "byte.h" | |
| 10 #include "cdb.h" | |
| 11 | |
| 12 void cdb_free(struct cdb *c) | |
| 13 { | |
| 14 if (c->map) { | |
| 15 munmap(c->map,c->size); | |
| 16 c->map = 0; | |
| 17 } | |
| 18 } | |
| 19 | |
| 20 void cdb_findstart(struct cdb *c) | |
| 21 { | |
| 22 c->loop = 0; | |
| 23 } | |
| 24 | |
| 25 void cdb_init(struct cdb *c,int fd) | |
| 26 { | |
| 27 struct stat st; | |
| 28 char *x; | |
| 29 | |
| 30 cdb_free(c); | |
| 31 cdb_findstart(c); | |
| 32 c->fd = fd; | |
| 33 | |
| 34 if (fstat(fd,&st) == 0) | |
| 35 if (st.st_size <= 0xffffffff) { | |
| 36 x = mmap(0,st.st_size,PROT_READ,MAP_SHARED,fd,0); | |
| 37 if (x + 1) { | |
| 38 c->size = st.st_size; | |
| 39 c->map = x; | |
| 40 } | |
| 41 } | |
| 42 } | |
| 43 | |
| 44 int cdb_read(struct cdb *c,char *buf,unsigned int len,uint32 pos) | |
| 45 { | |
| 46 if (c->map) { | |
| 47 if ((pos > c->size) || (c->size - pos < len)) goto FORMAT; | |
| 48 byte_copy(buf,len,c->map + pos); | |
| 49 } | |
| 50 else { | |
| 51 if (seek_set(c->fd,pos) == -1) return -1; | |
| 52 while (len > 0) { | |
| 53 int r; | |
| 54 do | |
| 55 r = read(c->fd,buf,len); | |
| 56 while ((r == -1) && (errno == error_intr)); | |
| 57 if (r == -1) return -1; | |
| 58 if (r == 0) goto FORMAT; | |
| 59 buf += r; | |
| 60 len -= r; | |
| 61 } | |
| 62 } | |
| 63 return 0; | |
| 64 | |
| 65 FORMAT: | |
| 66 errno = error_proto; | |
| 67 return -1; | |
| 68 } | |
| 69 | |
| 70 static int match(struct cdb *c,char *key,unsigned int len,uint32 pos) | |
| 71 { | |
| 72 char buf[32]; | |
| 73 int n; | |
| 74 | |
| 75 while (len > 0) { | |
| 76 n = sizeof buf; | |
| 77 if (n > len) n = len; | |
| 78 if (cdb_read(c,buf,n,pos) == -1) return -1; | |
| 79 if (byte_diff(buf,n,key)) return 0; | |
| 80 pos += n; | |
| 81 key += n; | |
| 82 len -= n; | |
| 83 } | |
| 84 return 1; | |
| 85 } | |
| 86 | |
| 87 int cdb_findnext(struct cdb *c,char *key,unsigned int len) | |
| 88 { | |
| 89 char buf[8]; | |
| 90 uint32 pos; | |
| 91 uint32 u; | |
| 92 | |
| 93 if (!c->loop) { | |
| 94 u = cdb_hash(key,len); | |
| 95 if (cdb_read(c,buf,8,(u << 3) & 2047) == -1) return -1; | |
| 96 uint32_unpack(buf + 4,&c->hslots); | |
| 97 if (!c->hslots) return 0; | |
| 98 uint32_unpack(buf,&c->hpos); | |
| 99 c->khash = u; | |
| 100 u >>= 8; | |
| 101 u %= c->hslots; | |
| 102 u <<= 3; | |
| 103 c->kpos = c->hpos + u; | |
| 104 } | |
| 105 | |
| 106 while (c->loop < c->hslots) { | |
| 107 if (cdb_read(c,buf,8,c->kpos) == -1) return -1; | |
| 108 uint32_unpack(buf + 4,&pos); | |
| 109 if (!pos) return 0; | |
| 110 c->loop += 1; | |
| 111 c->kpos += 8; | |
| 112 if (c->kpos == c->hpos + (c->hslots << 3)) c->kpos = c->hpos; | |
| 113 uint32_unpack(buf,&u); | |
| 114 if (u == c->khash) { | |
| 115 if (cdb_read(c,buf,8,pos) == -1) return -1; | |
| 116 uint32_unpack(buf,&u); | |
| 117 if (u == len) | |
| 118 switch(match(c,key,len,pos + 8)) { | |
| 119 case -1: | |
| 120 return -1; | |
| 121 case 1: | |
| 122 uint32_unpack(buf + 4,&c->dlen); | |
| 123 c->dpos = pos + 8 + len; | |
| 124 return 1; | |
| 125 } | |
| 126 } | |
| 127 } | |
| 128 | |
| 129 return 0; | |
| 130 } | |
| 131 | |
| 132 int cdb_find(struct cdb *c,char *key,unsigned int len) | |
| 133 { | |
| 134 cdb_findstart(c); | |
| 135 return cdb_findnext(c,key,len); | |
| 136 } |
