qdbm-1.8.78/0000755000175000017500000000000011426320070011537 5ustar mikiomikioqdbm-1.8.78/villa.c0000644000175000017500000023701110677717355013045 0ustar mikiomikio/************************************************************************************************* * Implementation of Villa * Copyright (C) 2000-2007 Mikio Hirabayashi * This file is part of QDBM, Quick Database Manager. * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU * Lesser General Public License as published by the Free Software Foundation; either version * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * You should have received a copy of the GNU Lesser General Public License along with QDBM; if * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. *************************************************************************************************/ #define QDBM_INTERNAL 1 #include "villa.h" #include "myconf.h" #define VL_LEAFIDMIN 1 /* minimum number of leaf ID */ #define VL_NODEIDMIN 100000000 /* minimum number of node ID */ #define VL_VNUMBUFSIZ 8 /* size of a buffer for variable length number */ #define VL_NUMBUFSIZ 32 /* size of a buffer for a number */ #define VL_PAGEBUFSIZ 32768 /* size of a buffer to read each page */ #define VL_MAXLEAFSIZ 49152 /* maximum size of each leaf */ #define VL_DEFLRECMAX 49 /* default number of records in each leaf */ #define VL_DEFNIDXMAX 192 /* default number of indexes in each node */ #define VL_DEFLCNUM 1024 /* default number of leaf cache */ #define VL_DEFNCNUM 512 /* default number of node cache */ #define VL_CACHEOUT 8 /* number of pages in a process of cacheout */ #define VL_INITBNUM 32749 /* initial bucket number */ #define VL_PAGEALIGN -3 /* alignment for pages */ #define VL_FBPOOLSIZ 128 /* size of free block pool */ #define VL_PATHBUFSIZ 1024 /* size of a path buffer */ #define VL_TMPFSUF MYEXTSTR "vltmp" /* suffix of a temporary file */ #define VL_ROOTKEY -1 /* key of the root key */ #define VL_LASTKEY -2 /* key of the last key */ #define VL_LNUMKEY -3 /* key of the number of leaves */ #define VL_NNUMKEY -4 /* key of the number of nodes */ #define VL_RNUMKEY -5 /* key of the number of records */ #define VL_CRDNUM 7 /* default division number for Vista */ /* set a buffer for a variable length number */ #define VL_SETVNUMBUF(VL_len, VL_buf, VL_num) \ do { \ int _VL_num; \ _VL_num = VL_num; \ if(_VL_num == 0){ \ ((signed char *)(VL_buf))[0] = 0; \ (VL_len) = 1; \ } else { \ (VL_len) = 0; \ while(_VL_num > 0){ \ int _VL_rem = _VL_num & 0x7f; \ _VL_num >>= 7; \ if(_VL_num > 0){ \ ((signed char *)(VL_buf))[(VL_len)] = -_VL_rem - 1; \ } else { \ ((signed char *)(VL_buf))[(VL_len)] = _VL_rem; \ } \ (VL_len)++; \ } \ } \ } while(FALSE) /* read a variable length buffer */ #define VL_READVNUMBUF(VL_buf, VL_size, VL_num, VL_step) \ do { \ int _VL_i, _VL_base; \ (VL_num) = 0; \ _VL_base = 1; \ if((VL_size) < 2){ \ (VL_num) = ((signed char *)(VL_buf))[0]; \ (VL_step) = 1; \ } else { \ for(_VL_i = 0; _VL_i < (VL_size); _VL_i++){ \ if(((signed char *)(VL_buf))[_VL_i] >= 0){ \ (VL_num) += ((signed char *)(VL_buf))[_VL_i] * _VL_base; \ break; \ } \ (VL_num) += _VL_base * (((signed char *)(VL_buf))[_VL_i] + 1) * -1; \ _VL_base *= 128; \ } \ (VL_step) = _VL_i + 1; \ } \ } while(FALSE) enum { /* enumeration for flags */ VL_FLISVILLA = 1 << 0, /* whether for Villa */ VL_FLISZLIB = 1 << 1, /* whether with ZLIB */ VL_FLISLZO = 1 << 2, /* whether with LZO */ VL_FLISBZIP = 1 << 3 /* whether with BZIP2 */ }; /* private function prototypes */ static int vllexcompare(const char *aptr, int asiz, const char *bptr, int bsiz); static int vlintcompare(const char *aptr, int asiz, const char *bptr, int bsiz); static int vlnumcompare(const char *aptr, int asiz, const char *bptr, int bsiz); static int vldeccompare(const char *aptr, int asiz, const char *bptr, int bsiz); static int vldpputnum(DEPOT *depot, int knum, int vnum); static int vldpgetnum(DEPOT *depot, int knum, int *vnp); static VLLEAF *vlleafnew(VILLA *villa, int prev, int next); static int vlleafcacheout(VILLA *villa, int id); static int vlleafsave(VILLA *villa, VLLEAF *leaf); static VLLEAF *vlleafload(VILLA *villa, int id); static VLLEAF *vlgethistleaf(VILLA *villa, const char *kbuf, int ksiz); static int vlleafaddrec(VILLA *villa, VLLEAF *leaf, int dmode, const char *kbuf, int ksiz, const char *vbuf, int vsiz); static int vlleafdatasize(VLLEAF *leaf); static VLLEAF *vlleafdivide(VILLA *villa, VLLEAF *leaf); static VLNODE *vlnodenew(VILLA *villa, int heir); static int vlnodecacheout(VILLA *villa, int id); static int vlnodesave(VILLA *villa, VLNODE *node); static VLNODE *vlnodeload(VILLA *villa, int id); static void vlnodeaddidx(VILLA *villa, VLNODE *node, int order, int pid, const char *kbuf, int ksiz); static int vlsearchleaf(VILLA *villa, const char *kbuf, int ksiz); static int vlcacheadjust(VILLA *villa); static VLREC *vlrecsearch(VILLA *villa, VLLEAF *leaf, const char *kbuf, int ksiz, int *ip); /************************************************************************************************* * public objects *************************************************************************************************/ /* Comparing functions. */ VLCFUNC VL_CMPLEX = vllexcompare; VLCFUNC VL_CMPINT = vlintcompare; VLCFUNC VL_CMPNUM = vlnumcompare; VLCFUNC VL_CMPDEC = vldeccompare; /* Get a database handle. */ VILLA *vlopen(const char *name, int omode, VLCFUNC cmp){ DEPOT *depot; int dpomode, flags, cmode, root, last, lnum, nnum, rnum; VILLA *villa; VLLEAF *leaf; assert(name && cmp); dpomode = DP_OREADER; if(omode & VL_OWRITER){ dpomode = DP_OWRITER; if(omode & VL_OCREAT) dpomode |= DP_OCREAT; if(omode & VL_OTRUNC) dpomode |= DP_OTRUNC; } if(omode & VL_ONOLCK) dpomode |= DP_ONOLCK; if(omode & VL_OLCKNB) dpomode |= DP_OLCKNB; if(!(depot = dpopen(name, dpomode, VL_INITBNUM))) return NULL; flags = dpgetflags(depot); cmode = 0; root = -1; last = -1; lnum = 0; nnum = 0; rnum = 0; if(dprnum(depot) > 0){ if(!(flags & VL_FLISVILLA) || !vldpgetnum(depot, VL_ROOTKEY, &root) || !vldpgetnum(depot, VL_LASTKEY, &last) || !vldpgetnum(depot, VL_LNUMKEY, &lnum) || !vldpgetnum(depot, VL_NNUMKEY, &nnum) || !vldpgetnum(depot, VL_RNUMKEY, &rnum) || root < VL_LEAFIDMIN || last < VL_LEAFIDMIN || lnum < 0 || nnum < 0 || rnum < 0){ dpclose(depot); dpecodeset(DP_EBROKEN, __FILE__, __LINE__); return NULL; } if(flags & VL_FLISZLIB){ cmode = VL_OZCOMP; } else if(flags & VL_FLISLZO){ cmode = VL_OYCOMP; } else if(flags & VL_FLISBZIP){ cmode = VL_OXCOMP; } } else if(omode & VL_OWRITER){ if(omode & VL_OZCOMP){ cmode = VL_OZCOMP; } else if(omode & VL_OYCOMP){ cmode = VL_OYCOMP; } else if(omode & VL_OXCOMP){ cmode = VL_OXCOMP; } } if(omode & VL_OWRITER){ flags |= VL_FLISVILLA; if(_qdbm_deflate && cmode == VL_OZCOMP){ flags |= VL_FLISZLIB; } else if(_qdbm_lzoencode && cmode == VL_OYCOMP){ flags |= VL_FLISLZO; } else if(_qdbm_bzencode && cmode == VL_OXCOMP){ flags |= VL_FLISBZIP; } if(!dpsetflags(depot, flags) || !dpsetalign(depot, VL_PAGEALIGN) || !dpsetfbpsiz(depot, VL_FBPOOLSIZ)){ dpclose(depot); return NULL; } } CB_MALLOC(villa, sizeof(VILLA)); villa->depot = depot; villa->cmp = cmp; villa->wmode = (omode & VL_OWRITER); villa->cmode = cmode; villa->root = root; villa->last = last; villa->lnum = lnum; villa->nnum = nnum; villa->rnum = rnum; villa->leafc = cbmapopen(); villa->nodec = cbmapopen(); villa->hnum = 0; villa->hleaf = -1; villa->lleaf = -1; villa->curleaf = -1; villa->curknum = -1; villa->curvnum = -1; villa->leafrecmax = VL_DEFLRECMAX; villa->nodeidxmax = VL_DEFNIDXMAX; villa->leafcnum = VL_DEFLCNUM; villa->nodecnum = VL_DEFNCNUM; villa->tran = FALSE; villa->rbroot = -1; villa->rblast = -1; villa->rblnum = -1; villa->rbnnum = -1; villa->rbrnum = -1; if(root == -1){ leaf = vlleafnew(villa, -1, -1); villa->root = leaf->id; villa->last = leaf->id; if(!vltranbegin(villa) || !vltranabort(villa)){ vlclose(villa); return NULL; } } return villa; } /* Close a database handle. */ int vlclose(VILLA *villa){ int err, pid; const char *tmp; assert(villa); err = FALSE; if(villa->tran){ if(!vltranabort(villa)) err = TRUE; } cbmapiterinit(villa->leafc); while((tmp = cbmapiternext(villa->leafc, NULL)) != NULL){ pid = *(int *)tmp; if(!vlleafcacheout(villa, pid)) err = TRUE; } cbmapiterinit(villa->nodec); while((tmp = cbmapiternext(villa->nodec, NULL)) != NULL){ pid = *(int *)tmp; if(!vlnodecacheout(villa, pid)) err = TRUE; } if(villa->wmode){ if(!dpsetalign(villa->depot, 0)) err = TRUE; if(!vldpputnum(villa->depot, VL_ROOTKEY, villa->root)) err = TRUE; if(!vldpputnum(villa->depot, VL_LASTKEY, villa->last)) err = TRUE; if(!vldpputnum(villa->depot, VL_LNUMKEY, villa->lnum)) err = TRUE; if(!vldpputnum(villa->depot, VL_NNUMKEY, villa->nnum)) err = TRUE; if(!vldpputnum(villa->depot, VL_RNUMKEY, villa->rnum)) err = TRUE; } cbmapclose(villa->leafc); cbmapclose(villa->nodec); if(!dpclose(villa->depot)) err = TRUE; free(villa); return err ? FALSE : TRUE; } /* Store a record. */ int vlput(VILLA *villa, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int dmode){ VLLEAF *leaf, *newleaf; VLNODE *node, *newnode; VLIDX *idxp; CBDATUM *key; int i, pid, todiv, heir, parent, mid; assert(villa && kbuf && vbuf); villa->curleaf = -1; villa->curknum = -1; villa->curvnum = -1; if(!villa->wmode){ dpecodeset(DP_EMODE, __FILE__, __LINE__); return FALSE; } if(ksiz < 0) ksiz = strlen(kbuf); if(vsiz < 0) vsiz = strlen(vbuf); if(villa->hleaf < VL_LEAFIDMIN || !(leaf = vlgethistleaf(villa, kbuf, ksiz))){ if((pid = vlsearchleaf(villa, kbuf, ksiz)) == -1) return FALSE; if(!(leaf = vlleafload(villa, pid))) return FALSE; } if(!vlleafaddrec(villa, leaf, dmode, kbuf, ksiz, vbuf, vsiz)){ dpecodeset(DP_EKEEP, __FILE__, __LINE__); return FALSE; } todiv = FALSE; switch(CB_LISTNUM(leaf->recs) % 4){ case 0: if(CB_LISTNUM(leaf->recs) >= 4 && vlleafdatasize(leaf) > VL_MAXLEAFSIZ * (villa->cmode > 0 ? 2 : 1)){ todiv = TRUE; break; } case 2: if(CB_LISTNUM(leaf->recs) > villa->leafrecmax) todiv = TRUE; break; } if(todiv){ if(!(newleaf = vlleafdivide(villa, leaf))) return FALSE; if(leaf->id == villa->last) villa->last = newleaf->id; heir = leaf->id; pid = newleaf->id; key = ((VLREC *)CB_LISTVAL(newleaf->recs, 0))->key; key = cbdatumdup(key); while(TRUE){ if(villa->hnum < 1){ node = vlnodenew(villa, heir); vlnodeaddidx(villa, node, TRUE, pid, CB_DATUMPTR(key), CB_DATUMSIZE(key)); villa->root = node->id; CB_DATUMCLOSE(key); break; } parent = villa->hist[--villa->hnum]; if(!(node = vlnodeload(villa, parent))){ CB_DATUMCLOSE(key); return FALSE; } vlnodeaddidx(villa, node, FALSE, pid, CB_DATUMPTR(key), CB_DATUMSIZE(key)); CB_DATUMCLOSE(key); if(CB_LISTNUM(node->idxs) <= villa->nodeidxmax || CB_LISTNUM(node->idxs) % 2 == 0) break; mid = CB_LISTNUM(node->idxs) / 2; idxp = (VLIDX *)CB_LISTVAL(node->idxs, mid); newnode = vlnodenew(villa, idxp->pid); heir = node->id; pid = newnode->id; CB_DATUMOPEN2(key, CB_DATUMPTR(idxp->key), CB_DATUMSIZE(idxp->key)); for(i = mid + 1; i < CB_LISTNUM(node->idxs); i++){ idxp = (VLIDX *)CB_LISTVAL(node->idxs, i); vlnodeaddidx(villa, newnode, TRUE, idxp->pid, CB_DATUMPTR(idxp->key), CB_DATUMSIZE(idxp->key)); } for(i = 0; i <= mid; i++){ idxp = (VLIDX *)cblistpop(node->idxs, NULL); CB_DATUMCLOSE(idxp->key); free(idxp); } node->dirty = TRUE; } } if(!villa->tran && !vlcacheadjust(villa)) return FALSE; return TRUE; } /* Delete a record. */ int vlout(VILLA *villa, const char *kbuf, int ksiz){ VLLEAF *leaf; VLREC *recp; int pid, ri, vsiz; char *vbuf; assert(villa && kbuf); villa->curleaf = -1; villa->curknum = -1; villa->curvnum = -1; if(!villa->wmode){ dpecodeset(DP_EMODE, __FILE__, __LINE__); return FALSE; } if(ksiz < 0) ksiz = strlen(kbuf); if(villa->hleaf < VL_LEAFIDMIN || !(leaf = vlgethistleaf(villa, kbuf, ksiz))){ if((pid = vlsearchleaf(villa, kbuf, ksiz)) == -1) return FALSE; if(!(leaf = vlleafload(villa, pid))) return FALSE; } if(!(recp = vlrecsearch(villa, leaf, kbuf, ksiz, &ri))){ dpecodeset(DP_ENOITEM, __FILE__, __LINE__); return FALSE; } if(recp->rest){ CB_DATUMCLOSE(recp->first); vbuf = cblistshift(recp->rest, &vsiz); CB_DATUMOPEN2(recp->first, vbuf, vsiz); free(vbuf); if(CB_LISTNUM(recp->rest) < 1){ CB_LISTCLOSE(recp->rest); recp->rest = NULL; } } else { CB_DATUMCLOSE(recp->key); CB_DATUMCLOSE(recp->first); free(cblistremove(leaf->recs, ri, NULL)); } leaf->dirty = TRUE; villa->rnum--; if(!villa->tran && !vlcacheadjust(villa)) return FALSE; return TRUE; } /* Retrieve a record. */ char *vlget(VILLA *villa, const char *kbuf, int ksiz, int *sp){ VLLEAF *leaf; VLREC *recp; char *rv; int pid; assert(villa && kbuf); if(ksiz < 0) ksiz = strlen(kbuf); if(villa->hleaf < VL_LEAFIDMIN || !(leaf = vlgethistleaf(villa, kbuf, ksiz))){ if((pid = vlsearchleaf(villa, kbuf, ksiz)) == -1) return NULL; if(!(leaf = vlleafload(villa, pid))) return NULL; } if(!(recp = vlrecsearch(villa, leaf, kbuf, ksiz, NULL))){ dpecodeset(DP_ENOITEM, __FILE__, __LINE__); return NULL; } if(!villa->tran && !vlcacheadjust(villa)) return NULL; if(sp) *sp = CB_DATUMSIZE(recp->first); CB_MEMDUP(rv, CB_DATUMPTR(recp->first), CB_DATUMSIZE(recp->first)); return rv; } /* Get the size of the value of a record. */ int vlvsiz(VILLA *villa, const char *kbuf, int ksiz){ VLLEAF *leaf; VLREC *recp; int pid; assert(villa && kbuf); if(ksiz < 0) ksiz = strlen(kbuf); if(villa->hleaf < VL_LEAFIDMIN || !(leaf = vlgethistleaf(villa, kbuf, ksiz))){ if((pid = vlsearchleaf(villa, kbuf, ksiz)) == -1) return -1; if(!(leaf = vlleafload(villa, pid))) return -1; } if(!(recp = vlrecsearch(villa, leaf, kbuf, ksiz, NULL))){ dpecodeset(DP_ENOITEM, __FILE__, __LINE__); return -1; } if(!villa->tran && !vlcacheadjust(villa)) return -1; return CB_DATUMSIZE(recp->first); } /* Get the number of records corresponding a key. */ int vlvnum(VILLA *villa, const char *kbuf, int ksiz){ VLLEAF *leaf; VLREC *recp; int pid; assert(villa && kbuf); if(ksiz < 0) ksiz = strlen(kbuf); if(villa->hleaf < VL_LEAFIDMIN || !(leaf = vlgethistleaf(villa, kbuf, ksiz))){ if((pid = vlsearchleaf(villa, kbuf, ksiz)) == -1) return 0; if(!(leaf = vlleafload(villa, pid))) return 0; } if(!(recp = vlrecsearch(villa, leaf, kbuf, ksiz, NULL))){ dpecodeset(DP_ENOITEM, __FILE__, __LINE__); return 0; } if(!villa->tran && !vlcacheadjust(villa)) return 0; return 1 + (recp->rest ? CB_LISTNUM(recp->rest) : 0); } /* Store plural records corresponding a key. */ int vlputlist(VILLA *villa, const char *kbuf, int ksiz, const CBLIST *vals){ int i, vsiz; const char *vbuf; assert(villa && kbuf && vals); if(!villa->wmode){ dpecodeset(DP_EMODE, __FILE__, __LINE__); return FALSE; } if(CB_LISTNUM(vals) < 1){ dpecodeset(DP_EMISC, __FILE__, __LINE__); return FALSE; } if(ksiz < 0) ksiz = strlen(kbuf); for(i = 0; i < CB_LISTNUM(vals); i++){ vbuf = CB_LISTVAL2(vals, i, vsiz); if(!vlput(villa, kbuf, ksiz, vbuf, vsiz, VL_DDUP)) return FALSE; } return TRUE; } /* Delete all records corresponding a key. */ int vloutlist(VILLA *villa, const char *kbuf, int ksiz){ int i, vnum; assert(villa && kbuf); if(!villa->wmode){ dpecodeset(DP_EMISC, __FILE__, __LINE__); return FALSE; } if(ksiz < 0) ksiz = strlen(kbuf); if((vnum = vlvnum(villa, kbuf, ksiz)) < 1) return FALSE; for(i = 0; i < vnum; i++){ if(!vlout(villa, kbuf, ksiz)) return FALSE; } return TRUE; } /* Retrieve values of all records corresponding a key. */ CBLIST *vlgetlist(VILLA *villa, const char *kbuf, int ksiz){ VLLEAF *leaf; VLREC *recp; int pid, i, vsiz; CBLIST *vals; const char *vbuf; assert(villa && kbuf); if(ksiz < 0) ksiz = strlen(kbuf); if(villa->hleaf < VL_LEAFIDMIN || !(leaf = vlgethistleaf(villa, kbuf, ksiz))){ if((pid = vlsearchleaf(villa, kbuf, ksiz)) == -1) return NULL; if(!(leaf = vlleafload(villa, pid))) return NULL; } if(!(recp = vlrecsearch(villa, leaf, kbuf, ksiz, NULL))){ dpecodeset(DP_ENOITEM, __FILE__, __LINE__); return NULL; } CB_LISTOPEN(vals); CB_LISTPUSH(vals, CB_DATUMPTR(recp->first), CB_DATUMSIZE(recp->first)); if(recp->rest){ for(i = 0; i < CB_LISTNUM(recp->rest); i++){ vbuf = CB_LISTVAL2(recp->rest, i, vsiz); CB_LISTPUSH(vals, vbuf, vsiz); } } if(!villa->tran && !vlcacheadjust(villa)){ CB_LISTCLOSE(vals); return NULL; } return vals; } /* Retrieve concatenated values of all records corresponding a key. */ char *vlgetcat(VILLA *villa, const char *kbuf, int ksiz, int *sp){ VLLEAF *leaf; VLREC *recp; int pid, i, vsiz, rsiz; char *rbuf; const char *vbuf; assert(villa && kbuf); if(ksiz < 0) ksiz = strlen(kbuf); if(villa->hleaf < VL_LEAFIDMIN || !(leaf = vlgethistleaf(villa, kbuf, ksiz))){ if((pid = vlsearchleaf(villa, kbuf, ksiz)) == -1) return NULL; if(!(leaf = vlleafload(villa, pid))) return NULL; } if(!(recp = vlrecsearch(villa, leaf, kbuf, ksiz, NULL))){ dpecodeset(DP_ENOITEM, __FILE__, __LINE__); return NULL; } rsiz = CB_DATUMSIZE(recp->first); CB_MALLOC(rbuf, rsiz + 1); memcpy(rbuf, CB_DATUMPTR(recp->first), rsiz); if(recp->rest){ for(i = 0; i < CB_LISTNUM(recp->rest); i++){ vbuf = CB_LISTVAL2(recp->rest, i, vsiz); CB_REALLOC(rbuf, rsiz + vsiz + 1); memcpy(rbuf + rsiz, vbuf, vsiz); rsiz += vsiz; } } rbuf[rsiz] = '\0'; if(!villa->tran && !vlcacheadjust(villa)){ free(rbuf); return NULL; } if(sp) *sp = rsiz; return rbuf; } /* Move the cursor to the first record. */ int vlcurfirst(VILLA *villa){ VLLEAF *leaf; assert(villa); villa->curleaf = VL_LEAFIDMIN; villa->curknum = 0; villa->curvnum = 0; if(!(leaf = vlleafload(villa, villa->curleaf))){ villa->curleaf = -1; return FALSE; } while(CB_LISTNUM(leaf->recs) < 1){ villa->curleaf = leaf->next; villa->curknum = 0; villa->curvnum = 0; if(villa->curleaf == -1){ dpecodeset(DP_ENOITEM, __FILE__, __LINE__); return FALSE; } if(!(leaf = vlleafload(villa, villa->curleaf))){ villa->curleaf = -1; return FALSE; } } return TRUE; } /* Move the cursor to the last record. */ int vlcurlast(VILLA *villa){ VLLEAF *leaf; VLREC *recp; assert(villa); villa->curleaf = villa->last; if(!(leaf = vlleafload(villa, villa->curleaf))){ villa->curleaf = -1; return FALSE; } while(CB_LISTNUM(leaf->recs) < 1){ villa->curleaf = leaf->prev; if(villa->curleaf == -1){ villa->curleaf = -1; dpecodeset(DP_ENOITEM, __FILE__, __LINE__); return FALSE; } if(!(leaf = vlleafload(villa, villa->curleaf))){ villa->curleaf = -1; return FALSE; } } villa->curknum = CB_LISTNUM(leaf->recs) - 1; recp = (VLREC *)CB_LISTVAL(leaf->recs, villa->curknum); villa->curvnum = recp->rest ? CB_LISTNUM(recp->rest) : 0; return TRUE; } /* Move the cursor to the previous record. */ int vlcurprev(VILLA *villa){ VLLEAF *leaf; VLREC *recp; assert(villa); if(villa->curleaf == -1){ dpecodeset(DP_ENOITEM, __FILE__, __LINE__); return FALSE; } if(!(leaf = vlleafload(villa, villa->curleaf)) || CB_LISTNUM(leaf->recs) < 1){ villa->curleaf = -1; return FALSE; } recp = (VLREC *)CB_LISTVAL(leaf->recs, villa->curknum); villa->curvnum--; if(villa->curvnum < 0){ villa->curknum--; if(villa->curknum < 0){ villa->curleaf = leaf->prev; if(villa->curleaf == -1){ villa->curleaf = -1; dpecodeset(DP_ENOITEM, __FILE__, __LINE__); return FALSE; } if(!(leaf = vlleafload(villa, villa->curleaf))){ villa->curleaf = -1; return FALSE; } while(CB_LISTNUM(leaf->recs) < 1){ villa->curleaf = leaf->prev; if(villa->curleaf == -1){ dpecodeset(DP_ENOITEM, __FILE__, __LINE__); return FALSE; } if(!(leaf = vlleafload(villa, villa->curleaf))){ villa->curleaf = -1; return FALSE; } } villa->curknum = CB_LISTNUM(leaf->recs) - 1; recp = (VLREC *)CB_LISTVAL(leaf->recs, villa->curknum); villa->curvnum = recp->rest ? CB_LISTNUM(recp->rest) : 0; } recp = (VLREC *)CB_LISTVAL(leaf->recs, villa->curknum); villa->curvnum = recp->rest ? CB_LISTNUM(recp->rest) : 0; } if(!villa->tran && !vlcacheadjust(villa)) return FALSE; return TRUE; } /* Move the cursor to the next record. */ int vlcurnext(VILLA *villa){ VLLEAF *leaf; VLREC *recp; assert(villa); if(villa->curleaf == -1){ dpecodeset(DP_ENOITEM, __FILE__, __LINE__); return FALSE; } if(!(leaf = vlleafload(villa, villa->curleaf)) || CB_LISTNUM(leaf->recs) < 1){ villa->curleaf = -1; return FALSE; } recp = (VLREC *)CB_LISTVAL(leaf->recs, villa->curknum); villa->curvnum++; if(villa->curvnum > (recp->rest ? CB_LISTNUM(recp->rest) : 0)){ villa->curknum++; villa->curvnum = 0; } if(villa->curknum >= CB_LISTNUM(leaf->recs)){ villa->curleaf = leaf->next; villa->curknum = 0; villa->curvnum = 0; if(villa->curleaf == -1){ dpecodeset(DP_ENOITEM, __FILE__, __LINE__); return FALSE; } if(!(leaf = vlleafload(villa, villa->curleaf))){ villa->curleaf = -1; return FALSE; } while(CB_LISTNUM(leaf->recs) < 1){ villa->curleaf = leaf->next; villa->curknum = 0; villa->curvnum = 0; if(villa->curleaf == -1){ dpecodeset(DP_ENOITEM, __FILE__, __LINE__); return FALSE; } if(!(leaf = vlleafload(villa, villa->curleaf))){ villa->curleaf = -1; return FALSE; } } } if(!villa->tran && !vlcacheadjust(villa)) return FALSE; return TRUE; } /* Move the cursor to a position around a record. */ int vlcurjump(VILLA *villa, const char *kbuf, int ksiz, int jmode){ VLLEAF *leaf; VLREC *recp; int pid, index; assert(villa && kbuf); if(ksiz < 0) ksiz = strlen(kbuf); if((pid = vlsearchleaf(villa, kbuf, ksiz)) == -1){ villa->curleaf = -1; return FALSE; } if(!(leaf = vlleafload(villa, pid))){ villa->curleaf = -1; return FALSE; } while(CB_LISTNUM(leaf->recs) < 1){ villa->curleaf = (jmode == VL_JFORWARD) ? leaf->next : leaf->prev; if(villa->curleaf == -1){ dpecodeset(DP_ENOITEM, __FILE__, __LINE__); return FALSE; } if(!(leaf = vlleafload(villa, villa->curleaf))){ villa->curleaf = -1; return FALSE; } } if(!(recp = vlrecsearch(villa, leaf, kbuf, ksiz, &index))){ if(jmode == VL_JFORWARD){ villa->curleaf = leaf->id; if(index >= CB_LISTNUM(leaf->recs)) index--; villa->curknum = index; villa->curvnum = 0; recp = (VLREC *)CB_LISTVAL(leaf->recs, index); if(villa->cmp(kbuf, ksiz, CB_DATUMPTR(recp->key), CB_DATUMSIZE(recp->key)) < 0) return TRUE; villa->curvnum = (recp->rest ? CB_LISTNUM(recp->rest) : 0); return vlcurnext(villa); } else { villa->curleaf = leaf->id; if(index >= CB_LISTNUM(leaf->recs)) index--; villa->curknum = index; recp = (VLREC *)CB_LISTVAL(leaf->recs, index); villa->curvnum = (recp->rest ? CB_LISTNUM(recp->rest) : 0); if(villa->cmp(kbuf, ksiz, CB_DATUMPTR(recp->key), CB_DATUMSIZE(recp->key)) > 0) return TRUE; villa->curvnum = 0; return vlcurprev(villa); } } if(jmode == VL_JFORWARD){ villa->curleaf = pid; villa->curknum = index; villa->curvnum = 0; } else { villa->curleaf = pid; villa->curknum = index; villa->curvnum = (recp->rest ? CB_LISTNUM(recp->rest) : 0); } return TRUE; } /* Get the key of the record where the cursor is. */ char *vlcurkey(VILLA *villa, int *sp){ VLLEAF *leaf; VLREC *recp; const char *kbuf; char *rv; int ksiz; assert(villa); if(villa->curleaf == -1){ dpecodeset(DP_ENOITEM, __FILE__, __LINE__); return FALSE; } if(!(leaf = vlleafload(villa, villa->curleaf))){ villa->curleaf = -1; return FALSE; } recp = (VLREC *)CB_LISTVAL(leaf->recs, villa->curknum); kbuf = CB_DATUMPTR(recp->key); ksiz = CB_DATUMSIZE(recp->key); if(sp) *sp = ksiz; CB_MEMDUP(rv, kbuf, ksiz); return rv; } /* Get the value of the record where the cursor is. */ char *vlcurval(VILLA *villa, int *sp){ VLLEAF *leaf; VLREC *recp; const char *vbuf; char *rv; int vsiz; assert(villa); if(villa->curleaf == -1){ dpecodeset(DP_ENOITEM, __FILE__, __LINE__); return FALSE; } if(!(leaf = vlleafload(villa, villa->curleaf))){ villa->curleaf = -1; return FALSE; } recp = (VLREC *)CB_LISTVAL(leaf->recs, villa->curknum); if(villa->curvnum < 1){ vbuf = CB_DATUMPTR(recp->first); vsiz = CB_DATUMSIZE(recp->first); } else { vbuf = CB_LISTVAL2(recp->rest, villa->curvnum - 1, vsiz); } if(sp) *sp = vsiz; CB_MEMDUP(rv, vbuf, vsiz); return rv; } /* Insert a record around the cursor. */ int vlcurput(VILLA *villa, const char *vbuf, int vsiz, int cpmode){ VLLEAF *leaf; VLREC *recp; char *tbuf; int tsiz; assert(villa && vbuf); if(!villa->wmode){ dpecodeset(DP_EMODE, __FILE__, __LINE__); return FALSE; } if(vsiz < 0) vsiz = strlen(vbuf); if(villa->curleaf == -1){ dpecodeset(DP_ENOITEM, __FILE__, __LINE__); return FALSE; } if(!(leaf = vlleafload(villa, villa->curleaf))){ villa->curleaf = -1; return FALSE; } recp = (VLREC *)CB_LISTVAL(leaf->recs, villa->curknum); switch(cpmode){ case VL_CPBEFORE: if(villa->curvnum < 1){ if(!recp->rest){ CB_DATUMTOMALLOC(recp->first, tbuf, tsiz); CB_DATUMOPEN2(recp->first, vbuf, vsiz); CB_LISTOPEN(recp->rest); CB_LISTPUSHBUF(recp->rest, tbuf, tsiz); } else { cblistunshift(recp->rest, CB_DATUMPTR(recp->first), CB_DATUMSIZE(recp->first)); CB_DATUMSETSIZE(recp->first, 0); CB_DATUMCAT(recp->first, vbuf, vsiz); } } else { CB_LISTINSERT(recp->rest, villa->curvnum - 1, vbuf, vsiz); } villa->rnum++; break; case VL_CPAFTER: if(!recp->rest) CB_LISTOPEN(recp->rest); CB_LISTINSERT(recp->rest, villa->curvnum, vbuf, vsiz); villa->curvnum++; villa->rnum++; break; default: if(villa->curvnum < 1){ CB_DATUMSETSIZE(recp->first, 0); CB_DATUMCAT(recp->first, vbuf, vsiz); } else { cblistover(recp->rest, villa->curvnum - 1, vbuf, vsiz); } break; } leaf->dirty = TRUE; return TRUE; } /* Delete the record where the cursor is. */ int vlcurout(VILLA *villa){ VLLEAF *leaf; VLREC *recp; char *vbuf; int vsiz; assert(villa); if(!villa->wmode){ dpecodeset(DP_EMODE, __FILE__, __LINE__); return FALSE; } if(villa->curleaf == -1){ dpecodeset(DP_ENOITEM, __FILE__, __LINE__); return FALSE; } if(!(leaf = vlleafload(villa, villa->curleaf))){ villa->curleaf = -1; return FALSE; } recp = (VLREC *)CB_LISTVAL(leaf->recs, villa->curknum); if(villa->curvnum < 1){ if(recp->rest){ vbuf = cblistshift(recp->rest, &vsiz); CB_DATUMSETSIZE(recp->first, 0); CB_DATUMCAT(recp->first, vbuf, vsiz); free(vbuf); if(CB_LISTNUM(recp->rest) < 1){ CB_LISTCLOSE(recp->rest); recp->rest = NULL; } } else { CB_DATUMCLOSE(recp->first); CB_DATUMCLOSE(recp->key); free(cblistremove(leaf->recs, villa->curknum, NULL)); } } else { free(cblistremove(recp->rest, villa->curvnum - 1, NULL)); if(villa->curvnum - 1 >= CB_LISTNUM(recp->rest)){ villa->curknum++; villa->curvnum = 0; } if(CB_LISTNUM(recp->rest) < 1){ CB_LISTCLOSE(recp->rest); recp->rest = NULL; } } villa->rnum--; leaf->dirty = TRUE; if(villa->curknum >= CB_LISTNUM(leaf->recs)){ villa->curleaf = leaf->next; villa->curknum = 0; villa->curvnum = 0; while(villa->curleaf != -1 && (leaf = vlleafload(villa, villa->curleaf)) != NULL && CB_LISTNUM(leaf->recs) < 1){ villa->curleaf = leaf->next; } } return TRUE; } /* Set the tuning parameters for performance. */ void vlsettuning(VILLA *villa, int lrecmax, int nidxmax, int lcnum, int ncnum){ assert(villa); if(lrecmax < 1) lrecmax = VL_DEFLRECMAX; if(lrecmax < 3) lrecmax = 3; if(nidxmax < 1) nidxmax = VL_DEFNIDXMAX; if(nidxmax < 4) nidxmax = 4; if(lcnum < 1) lcnum = VL_DEFLCNUM; if(lcnum < VL_CACHEOUT * 2) lcnum = VL_CACHEOUT * 2; if(ncnum < 1) ncnum = VL_DEFNCNUM; if(ncnum < VL_CACHEOUT * 2) ncnum = VL_CACHEOUT * 2; villa->leafrecmax = lrecmax; villa->nodeidxmax = nidxmax; villa->leafcnum = lcnum; villa->nodecnum = ncnum; } /* Set the size of the free block pool of a database handle. */ int vlsetfbpsiz(VILLA *villa, int size){ assert(villa && size >= 0); if(!villa->wmode){ dpecodeset(DP_EMODE, __FILE__, __LINE__); return FALSE; } return dpsetfbpsiz(villa->depot, size); } /* Synchronize updating contents with the file and the device. */ int vlsync(VILLA *villa){ int err; err = FALSE; if(!vlmemsync(villa)) err = TRUE; if(!dpsync(villa->depot)) err = TRUE; return err ? FALSE : TRUE; } /* Optimize a database. */ int vloptimize(VILLA *villa){ int err; assert(villa); if(!villa->wmode){ dpecodeset(DP_EMODE, __FILE__, __LINE__); return FALSE; } if(villa->tran){ dpecodeset(DP_EMISC, __FILE__, __LINE__); return FALSE; } err = FALSE; if(!vlsync(villa)) return FALSE; if(!dpoptimize(villa->depot, -1)) err = TRUE; return err ? FALSE : TRUE; } /* Get the name of a database. */ char *vlname(VILLA *villa){ assert(villa); return dpname(villa->depot); } /* Get the size of a database file. */ int vlfsiz(VILLA *villa){ return dpfsiz(villa->depot); } /* Get the number of the leaf nodes of B+ tree. */ int vllnum(VILLA *villa){ assert(villa); return villa->lnum; } /* Get the number of the non-leaf nodes of B+ tree. */ int vlnnum(VILLA *villa){ assert(villa); return villa->nnum; } /* Get the number of the records stored in a database. */ int vlrnum(VILLA *villa){ assert(villa); return villa->rnum; } /* Check whether a database handle is a writer or not. */ int vlwritable(VILLA *villa){ assert(villa); return villa->wmode; } /* Check whether a database has a fatal error or not. */ int vlfatalerror(VILLA *villa){ assert(villa); return dpfatalerror(villa->depot); } /* Get the inode number of a database file. */ int vlinode(VILLA *villa){ assert(villa); return dpinode(villa->depot); } /* Get the last modified time of a database. */ time_t vlmtime(VILLA *villa){ assert(villa); return dpmtime(villa->depot); } /* Begin the transaction. */ int vltranbegin(VILLA *villa){ int err, pid; const char *tmp; VLLEAF *leaf; VLNODE *node; assert(villa); if(!villa->wmode){ dpecodeset(DP_EMODE, __FILE__, __LINE__); return FALSE; } if(villa->tran){ dpecodeset(DP_EMISC, __FILE__, __LINE__); return FALSE; } err = FALSE; cbmapiterinit(villa->leafc); while((tmp = cbmapiternext(villa->leafc, NULL)) != NULL){ pid = *(int *)tmp; leaf = (VLLEAF *)cbmapget(villa->leafc, (char *)&pid, sizeof(int), NULL); if(leaf->dirty && !vlleafsave(villa, leaf)) err = TRUE; } cbmapiterinit(villa->nodec); while((tmp = cbmapiternext(villa->nodec, NULL)) != NULL){ pid = *(int *)tmp; node = (VLNODE *)cbmapget(villa->nodec, (char *)&pid, sizeof(int), NULL); if(node->dirty && !vlnodesave(villa, node)) err = TRUE; } if(!dpsetalign(villa->depot, 0)) err = TRUE; if(!vldpputnum(villa->depot, VL_ROOTKEY, villa->root)) err = TRUE; if(!vldpputnum(villa->depot, VL_LASTKEY, villa->last)) err = TRUE; if(!vldpputnum(villa->depot, VL_LNUMKEY, villa->lnum)) err = TRUE; if(!vldpputnum(villa->depot, VL_NNUMKEY, villa->nnum)) err = TRUE; if(!vldpputnum(villa->depot, VL_RNUMKEY, villa->rnum)) err = TRUE; if(!dpmemsync(villa->depot)) err = TRUE; if(!dpsetalign(villa->depot, VL_PAGEALIGN)) err = TRUE; villa->tran = TRUE; villa->rbroot = villa->root; villa->rblast = villa->last; villa->rblnum = villa->lnum; villa->rbnnum = villa->nnum; villa->rbrnum = villa->rnum; return err ? FALSE : TRUE; } /* Commit the transaction. */ int vltrancommit(VILLA *villa){ int err, pid; const char *tmp; VLLEAF *leaf; VLNODE *node; assert(villa); if(!villa->wmode){ dpecodeset(DP_EMODE, __FILE__, __LINE__); return FALSE; } if(!villa->tran){ dpecodeset(DP_EMISC, __FILE__, __LINE__); return FALSE; } err = FALSE; cbmapiterinit(villa->leafc); while((tmp = cbmapiternext(villa->leafc, NULL)) != NULL){ pid = *(int *)tmp; leaf = (VLLEAF *)cbmapget(villa->leafc, (char *)&pid, sizeof(int), NULL); if(leaf->dirty && !vlleafsave(villa, leaf)) err = TRUE; } cbmapiterinit(villa->nodec); while((tmp = cbmapiternext(villa->nodec, NULL)) != NULL){ pid = *(int *)tmp; node = (VLNODE *)cbmapget(villa->nodec, (char *)&pid, sizeof(int), NULL); if(node->dirty && !vlnodesave(villa, node)) err = TRUE; } if(!dpsetalign(villa->depot, 0)) err = TRUE; if(!vldpputnum(villa->depot, VL_ROOTKEY, villa->root)) err = TRUE; if(!vldpputnum(villa->depot, VL_LASTKEY, villa->last)) err = TRUE; if(!vldpputnum(villa->depot, VL_LNUMKEY, villa->lnum)) err = TRUE; if(!vldpputnum(villa->depot, VL_NNUMKEY, villa->nnum)) err = TRUE; if(!vldpputnum(villa->depot, VL_RNUMKEY, villa->rnum)) err = TRUE; if(!dpmemsync(villa->depot)) err = TRUE; if(!dpsetalign(villa->depot, VL_PAGEALIGN)) err = TRUE; villa->tran = FALSE; villa->rbroot = -1; villa->rblast = -1; villa->rblnum = -1; villa->rbnnum = -1; villa->rbrnum = -1; while(cbmaprnum(villa->leafc) > villa->leafcnum || cbmaprnum(villa->nodec) > villa->nodecnum){ if(!vlcacheadjust(villa)){ err = TRUE; break; } } return err ? FALSE : TRUE; } /* Abort the transaction. */ int vltranabort(VILLA *villa){ int err, pid; const char *tmp; VLLEAF *leaf; VLNODE *node; assert(villa); if(!villa->wmode){ dpecodeset(DP_EMODE, __FILE__, __LINE__); return FALSE; } if(!villa->tran){ dpecodeset(DP_EMISC, __FILE__, __LINE__); return FALSE; } err = FALSE; cbmapiterinit(villa->leafc); while((tmp = cbmapiternext(villa->leafc, NULL)) != NULL){ pid = *(int *)tmp; if(!(leaf = (VLLEAF *)cbmapget(villa->leafc, (char *)&pid, sizeof(int), NULL))){ err = TRUE; continue; } if(leaf->dirty){ leaf->dirty = FALSE; if(!vlleafcacheout(villa, pid)) err = TRUE; } } cbmapiterinit(villa->nodec); while((tmp = cbmapiternext(villa->nodec, NULL)) != NULL){ pid = *(int *)tmp; if(!(node = (VLNODE *)cbmapget(villa->nodec, (char *)&pid, sizeof(int), NULL))){ err = TRUE; continue; } if(node->dirty){ node->dirty = FALSE; if(!vlnodecacheout(villa, pid)) err = TRUE; } } villa->tran = FALSE; villa->root = villa->rbroot; villa->last = villa->rblast; villa->lnum = villa->rblnum; villa->nnum = villa->rbnnum; villa->rnum = villa->rbrnum; while(cbmaprnum(villa->leafc) > villa->leafcnum || cbmaprnum(villa->nodec) > villa->nodecnum){ if(!vlcacheadjust(villa)){ err = TRUE; break; } } return err ? FALSE : TRUE; } /* Remove a database file. */ int vlremove(const char *name){ assert(name); return dpremove(name); } /* Repair a broken database file. */ int vlrepair(const char *name, VLCFUNC cmp){ DEPOT *depot; VILLA *tvilla; char path[VL_PATHBUFSIZ], *kbuf, *vbuf, *zbuf, *rp, *tkbuf, *tvbuf; int i, err, flags, omode, ksiz, vsiz, zsiz, size, step, tksiz, tvsiz, vnum; assert(name && cmp); err = FALSE; if(!dprepair(name)) err = TRUE; if(!(depot = dpopen(name, DP_OREADER, -1))) return FALSE; flags = dpgetflags(depot); if(!(flags & VL_FLISVILLA)){ dpclose(depot); dpecodeset(DP_EBROKEN, __FILE__, __LINE__); return FALSE; } sprintf(path, "%s%s", name, VL_TMPFSUF); omode = VL_OWRITER | VL_OCREAT | VL_OTRUNC; if(flags & VL_FLISZLIB){ omode |= VL_OZCOMP; } else if(flags & VL_FLISLZO){ omode |= VL_OXCOMP; } else if(flags & VL_FLISBZIP){ omode |= VL_OYCOMP; } if(!(tvilla = vlopen(path, omode, cmp))){ dpclose(depot); return FALSE; } if(!dpiterinit(depot)) err = TRUE; while((kbuf = dpiternext(depot, &ksiz)) != NULL){ if(ksiz == sizeof(int) && *(int *)kbuf < VL_NODEIDMIN && *(int *)kbuf > 0){ if((vbuf = dpget(depot, (char *)kbuf, sizeof(int), 0, -1, &vsiz)) != NULL){ if(_qdbm_inflate && (flags & VL_FLISZLIB) && (zbuf = _qdbm_inflate(vbuf, vsiz, &zsiz, _QDBM_ZMRAW)) != NULL){ free(vbuf); vbuf = zbuf; vsiz = zsiz; } else if(_qdbm_lzodecode && (flags & VL_FLISLZO) && (zbuf = _qdbm_lzodecode(vbuf, vsiz, &zsiz)) != NULL){ free(vbuf); vbuf = zbuf; vsiz = zsiz; } else if(_qdbm_bzdecode && (flags & VL_FLISBZIP) && (zbuf = _qdbm_bzdecode(vbuf, vsiz, &zsiz)) != NULL){ free(vbuf); vbuf = zbuf; vsiz = zsiz; } rp = vbuf; size = vsiz; if(size >= 1){ VL_READVNUMBUF(rp, size, vnum, step); rp += step; size -= step; } if(size >= 1){ VL_READVNUMBUF(rp, size, vnum, step); rp += step; size -= step; } while(size >= 1){ VL_READVNUMBUF(rp, size, tksiz, step); rp += step; size -= step; if(size < tksiz) break; tkbuf = rp; rp += tksiz; size -= tksiz; if(size < 1) break; VL_READVNUMBUF(rp, size, vnum, step); rp += step; size -= step; if(vnum < 1 || size < 1) break; for(i = 0; i < vnum && size >= 1; i++){ VL_READVNUMBUF(rp, size, tvsiz, step); rp += step; size -= step; if(size < tvsiz) break; tvbuf = rp; rp += tvsiz; size -= tvsiz; if(!vlput(tvilla, tkbuf, tksiz, tvbuf, tvsiz, VL_DDUP)) err = TRUE; } } free(vbuf); } } free(kbuf); } if(!vlclose(tvilla)) err = TRUE; if(!dpclose(depot)) err = TRUE; if(!dpremove(name)) err = TRUE; if(rename(path, name) == -1){ if(!err) dpecodeset(DP_EMISC, __FILE__, __LINE__); err = TRUE; } return err ? FALSE : TRUE; } /* Dump all records as endian independent data. */ int vlexportdb(VILLA *villa, const char *name){ DEPOT *depot; char path[VL_PATHBUFSIZ], *kbuf, *vbuf, *nkey; int i, err, ksiz, vsiz, ki; assert(villa && name); sprintf(path, "%s%s", name, VL_TMPFSUF); if(!(depot = dpopen(path, DP_OWRITER | DP_OCREAT | DP_OTRUNC, -1))) return FALSE; err = FALSE; vlcurfirst(villa); for(i = 0; !err && (kbuf = vlcurkey(villa, &ksiz)) != NULL; i++){ if((vbuf = vlcurval(villa, &vsiz)) != NULL){ CB_MALLOC(nkey, ksiz + VL_NUMBUFSIZ); ki = sprintf(nkey, "%X\t", i); memcpy(nkey + ki, kbuf, ksiz); if(!dpput(depot, nkey, ki + ksiz, vbuf, vsiz, DP_DKEEP)) err = TRUE; free(nkey); free(vbuf); } else { err = TRUE; } free(kbuf); vlcurnext(villa); } if(!dpexportdb(depot, name)) err = TRUE; if(!dpclose(depot)) err = TRUE; if(!dpremove(path)) err = TRUE; return !err && !vlfatalerror(villa); } /* Load all records from endian independent data. */ int vlimportdb(VILLA *villa, const char *name){ DEPOT *depot; char path[VL_PATHBUFSIZ], *kbuf, *vbuf, *rp; int err, ksiz, vsiz; assert(villa && name); if(!villa->wmode){ dpecodeset(DP_EMODE, __FILE__, __LINE__); return FALSE; } if(vlrnum(villa) > 0){ dpecodeset(DP_EMISC, __FILE__, __LINE__); return FALSE; } kbuf = dpname(villa->depot); sprintf(path, "%s%s", kbuf, VL_TMPFSUF); free(kbuf); if(!(depot = dpopen(path, DP_OWRITER | DP_OCREAT | DP_OTRUNC, -1))) return FALSE; err = FALSE; if(!dpimportdb(depot, name)) err = TRUE; dpiterinit(depot); while(!err && (kbuf = dpiternext(depot, &ksiz)) != NULL){ if((vbuf = dpget(depot, kbuf, ksiz, 0, -1, &vsiz)) != NULL){ if((rp = strchr(kbuf, '\t')) != NULL){ rp++; if(!vlput(villa, rp, ksiz - (rp - kbuf), vbuf, vsiz, VL_DDUP)) err = TRUE; } else { dpecodeset(DP_EBROKEN, __FILE__, __LINE__); err = TRUE; } free(vbuf); } else { err = TRUE; } free(kbuf); } if(!dpclose(depot)) err = TRUE; if(!dpremove(path)) err = TRUE; return !err && !vlfatalerror(villa); } /************************************************************************************************* * features for experts *************************************************************************************************/ /* Number of division of the database for Vista. */ int *vlcrdnumptr(void){ static int defvlcrdnum = VL_CRDNUM; void *ptr; if(_qdbm_ptsafe){ if(!(ptr = _qdbm_settsd(&defvlcrdnum, sizeof(int), &defvlcrdnum))){ defvlcrdnum = DP_EMISC; return &defvlcrdnum; } return (int *)ptr; } return &defvlcrdnum; } /* Synchronize updating contents on memory. */ int vlmemsync(VILLA *villa){ int err, pid; const char *tmp; assert(villa); if(!villa->wmode){ dpecodeset(DP_EMODE, __FILE__, __LINE__); return FALSE; } if(villa->tran){ dpecodeset(DP_EMISC, __FILE__, __LINE__); return FALSE; } err = FALSE; cbmapiterinit(villa->leafc); while((tmp = cbmapiternext(villa->leafc, NULL)) != NULL){ pid = *(int *)tmp; if(!vlleafcacheout(villa, pid)) err = TRUE; } cbmapiterinit(villa->nodec); while((tmp = cbmapiternext(villa->nodec, NULL)) != NULL){ pid = *(int *)tmp; if(!vlnodecacheout(villa, pid)) err = TRUE; } if(!dpsetalign(villa->depot, 0)) err = TRUE; if(!vldpputnum(villa->depot, VL_ROOTKEY, villa->root)) err = TRUE; if(!vldpputnum(villa->depot, VL_LASTKEY, villa->last)) err = TRUE; if(!vldpputnum(villa->depot, VL_LNUMKEY, villa->lnum)) err = TRUE; if(!vldpputnum(villa->depot, VL_NNUMKEY, villa->nnum)) err = TRUE; if(!vldpputnum(villa->depot, VL_RNUMKEY, villa->rnum)) err = TRUE; if(!dpsetalign(villa->depot, VL_PAGEALIGN)) err = TRUE; if(!dpmemsync(villa->depot)) err = TRUE; return err ? FALSE : TRUE; } /* Synchronize updating contents on memory, not physically. */ int vlmemflush(VILLA *villa){ int err, pid; const char *tmp; assert(villa); if(!villa->wmode){ dpecodeset(DP_EMODE, __FILE__, __LINE__); return FALSE; } if(villa->tran){ dpecodeset(DP_EMISC, __FILE__, __LINE__); return FALSE; } err = FALSE; cbmapiterinit(villa->leafc); while((tmp = cbmapiternext(villa->leafc, NULL)) != NULL){ pid = *(int *)tmp; if(!vlleafcacheout(villa, pid)) err = TRUE; } cbmapiterinit(villa->nodec); while((tmp = cbmapiternext(villa->nodec, NULL)) != NULL){ pid = *(int *)tmp; if(!vlnodecacheout(villa, pid)) err = TRUE; } if(!dpsetalign(villa->depot, 0)) err = TRUE; if(!vldpputnum(villa->depot, VL_ROOTKEY, villa->root)) err = TRUE; if(!vldpputnum(villa->depot, VL_LASTKEY, villa->last)) err = TRUE; if(!vldpputnum(villa->depot, VL_LNUMKEY, villa->lnum)) err = TRUE; if(!vldpputnum(villa->depot, VL_NNUMKEY, villa->nnum)) err = TRUE; if(!vldpputnum(villa->depot, VL_RNUMKEY, villa->rnum)) err = TRUE; if(!dpsetalign(villa->depot, VL_PAGEALIGN)) err = TRUE; if(!dpmemflush(villa->depot)) err = TRUE; return err ? FALSE : TRUE; } /* Refer to a volatile cache of a value of a record. */ const char *vlgetcache(VILLA *villa, const char *kbuf, int ksiz, int *sp){ VLLEAF *leaf; VLREC *recp; int pid; assert(villa && kbuf); if(ksiz < 0) ksiz = strlen(kbuf); if(villa->hleaf < VL_LEAFIDMIN || !(leaf = vlgethistleaf(villa, kbuf, ksiz))){ if((pid = vlsearchleaf(villa, kbuf, ksiz)) == -1) return NULL; if(!(leaf = vlleafload(villa, pid))) return NULL; } if(!(recp = vlrecsearch(villa, leaf, kbuf, ksiz, NULL))){ dpecodeset(DP_ENOITEM, __FILE__, __LINE__); return NULL; } if(!villa->tran && !vlcacheadjust(villa)) return NULL; if(sp) *sp = CB_DATUMSIZE(recp->first); return CB_DATUMPTR(recp->first); } /* Refer to volatile cache of the key of the record where the cursor is. */ const char *vlcurkeycache(VILLA *villa, int *sp){ VLLEAF *leaf; VLREC *recp; const char *kbuf; int ksiz; assert(villa); if(villa->curleaf == -1){ dpecodeset(DP_ENOITEM, __FILE__, __LINE__); return FALSE; } if(!(leaf = vlleafload(villa, villa->curleaf))){ villa->curleaf = -1; return FALSE; } recp = (VLREC *)CB_LISTVAL(leaf->recs, villa->curknum); kbuf = CB_DATUMPTR(recp->key); ksiz = CB_DATUMSIZE(recp->key); if(sp) *sp = ksiz; return kbuf; } /* Refer to volatile cache of the value of the record where the cursor is. */ const char *vlcurvalcache(VILLA *villa, int *sp){ VLLEAF *leaf; VLREC *recp; const char *vbuf; int vsiz; assert(villa); if(villa->curleaf == -1){ dpecodeset(DP_ENOITEM, __FILE__, __LINE__); return FALSE; } if(!(leaf = vlleafload(villa, villa->curleaf))){ villa->curleaf = -1; return FALSE; } recp = (VLREC *)CB_LISTVAL(leaf->recs, villa->curknum); if(villa->curvnum < 1){ vbuf = CB_DATUMPTR(recp->first); vsiz = CB_DATUMSIZE(recp->first); } else { vbuf = CB_LISTVAL2(recp->rest, villa->curvnum - 1, vsiz); } if(sp) *sp = vsiz; return vbuf; } /* Get a multiple cursor handle. */ VLMULCUR *vlmulcuropen(VILLA *villa){ VLMULCUR *mulcur; assert(villa); if(villa->wmode){ dpecodeset(DP_EMODE, __FILE__, __LINE__); return NULL; } CB_MALLOC(mulcur, sizeof(VLMULCUR)); mulcur->villa = villa; mulcur->curleaf = -1; mulcur->curknum = -1; mulcur->curvnum = -1; return mulcur; } /* Close a multiple cursor handle. */ void vlmulcurclose(VLMULCUR *mulcur){ assert(mulcur); free(mulcur); } /* Move a multiple cursor to the first record. */ int vlmulcurfirst(VLMULCUR *mulcur){ VLMULCUR swap; int rv; assert(mulcur); swap.curleaf = mulcur->villa->curleaf; swap.curknum = mulcur->villa->curknum; swap.curvnum = mulcur->villa->curvnum; mulcur->villa->curleaf = mulcur->curleaf; mulcur->villa->curknum = mulcur->curknum; mulcur->villa->curvnum = mulcur->curvnum; rv = vlcurfirst(mulcur->villa); mulcur->curleaf = mulcur->villa->curleaf; mulcur->curknum = mulcur->villa->curknum; mulcur->curvnum = mulcur->villa->curvnum; mulcur->villa->curleaf = swap.curleaf; mulcur->villa->curknum = swap.curknum; mulcur->villa->curvnum = swap.curvnum; return rv; } /* Move a multiple cursor to the last record. */ int vlmulcurlast(VLMULCUR *mulcur){ VLMULCUR swap; int rv; assert(mulcur); swap.curleaf = mulcur->villa->curleaf; swap.curknum = mulcur->villa->curknum; swap.curvnum = mulcur->villa->curvnum; mulcur->villa->curleaf = mulcur->curleaf; mulcur->villa->curknum = mulcur->curknum; mulcur->villa->curvnum = mulcur->curvnum; rv = vlcurlast(mulcur->villa); mulcur->curleaf = mulcur->villa->curleaf; mulcur->curknum = mulcur->villa->curknum; mulcur->curvnum = mulcur->villa->curvnum; mulcur->villa->curleaf = swap.curleaf; mulcur->villa->curknum = swap.curknum; mulcur->villa->curvnum = swap.curvnum; return rv; } /* Move a multiple cursor to the previous record. */ int vlmulcurprev(VLMULCUR *mulcur){ VLMULCUR swap; int rv; assert(mulcur); swap.curleaf = mulcur->villa->curleaf; swap.curknum = mulcur->villa->curknum; swap.curvnum = mulcur->villa->curvnum; mulcur->villa->curleaf = mulcur->curleaf; mulcur->villa->curknum = mulcur->curknum; mulcur->villa->curvnum = mulcur->curvnum; rv = vlcurprev(mulcur->villa); mulcur->curleaf = mulcur->villa->curleaf; mulcur->curknum = mulcur->villa->curknum; mulcur->curvnum = mulcur->villa->curvnum; mulcur->villa->curleaf = swap.curleaf; mulcur->villa->curknum = swap.curknum; mulcur->villa->curvnum = swap.curvnum; return rv; } /* Move a multiple cursor to the next record. */ int vlmulcurnext(VLMULCUR *mulcur){ VLMULCUR swap; int rv; assert(mulcur); swap.curleaf = mulcur->villa->curleaf; swap.curknum = mulcur->villa->curknum; swap.curvnum = mulcur->villa->curvnum; mulcur->villa->curleaf = mulcur->curleaf; mulcur->villa->curknum = mulcur->curknum; mulcur->villa->curvnum = mulcur->curvnum; rv = vlcurnext(mulcur->villa); mulcur->curleaf = mulcur->villa->curleaf; mulcur->curknum = mulcur->villa->curknum; mulcur->curvnum = mulcur->villa->curvnum; mulcur->villa->curleaf = swap.curleaf; mulcur->villa->curknum = swap.curknum; mulcur->villa->curvnum = swap.curvnum; return rv; } /* Move a multiple cursor to a position around a record. */ int vlmulcurjump(VLMULCUR *mulcur, const char *kbuf, int ksiz, int jmode){ VLMULCUR swap; int rv; assert(mulcur); swap.curleaf = mulcur->villa->curleaf; swap.curknum = mulcur->villa->curknum; swap.curvnum = mulcur->villa->curvnum; mulcur->villa->curleaf = mulcur->curleaf; mulcur->villa->curknum = mulcur->curknum; mulcur->villa->curvnum = mulcur->curvnum; rv = vlcurjump(mulcur->villa, kbuf, ksiz, jmode); mulcur->curleaf = mulcur->villa->curleaf; mulcur->curknum = mulcur->villa->curknum; mulcur->curvnum = mulcur->villa->curvnum; mulcur->villa->curleaf = swap.curleaf; mulcur->villa->curknum = swap.curknum; mulcur->villa->curvnum = swap.curvnum; return rv; } /* Get the key of the record where a multiple cursor is. */ char *vlmulcurkey(VLMULCUR *mulcur, int *sp){ VLMULCUR swap; char *rv; assert(mulcur); swap.curleaf = mulcur->villa->curleaf; swap.curknum = mulcur->villa->curknum; swap.curvnum = mulcur->villa->curvnum; mulcur->villa->curleaf = mulcur->curleaf; mulcur->villa->curknum = mulcur->curknum; mulcur->villa->curvnum = mulcur->curvnum; rv = vlcurkey(mulcur->villa, sp); mulcur->curleaf = mulcur->villa->curleaf; mulcur->curknum = mulcur->villa->curknum; mulcur->curvnum = mulcur->villa->curvnum; mulcur->villa->curleaf = swap.curleaf; mulcur->villa->curknum = swap.curknum; mulcur->villa->curvnum = swap.curvnum; return rv; } /* Get the value of the record where a multiple cursor is. */ char *vlmulcurval(VLMULCUR *mulcur, int *sp){ VLMULCUR swap; char *rv; assert(mulcur); swap.curleaf = mulcur->villa->curleaf; swap.curknum = mulcur->villa->curknum; swap.curvnum = mulcur->villa->curvnum; mulcur->villa->curleaf = mulcur->curleaf; mulcur->villa->curknum = mulcur->curknum; mulcur->villa->curvnum = mulcur->curvnum; rv = vlcurval(mulcur->villa, sp); mulcur->curleaf = mulcur->villa->curleaf; mulcur->curknum = mulcur->villa->curknum; mulcur->curvnum = mulcur->villa->curvnum; mulcur->villa->curleaf = swap.curleaf; mulcur->villa->curknum = swap.curknum; mulcur->villa->curvnum = swap.curvnum; return rv; } /* Refer to volatile cache of the key of the record where a multiple cursor is. */ const char *vlmulcurkeycache(VLMULCUR *mulcur, int *sp){ VLMULCUR swap; const char *rv; assert(mulcur); swap.curleaf = mulcur->villa->curleaf; swap.curknum = mulcur->villa->curknum; swap.curvnum = mulcur->villa->curvnum; mulcur->villa->curleaf = mulcur->curleaf; mulcur->villa->curknum = mulcur->curknum; mulcur->villa->curvnum = mulcur->curvnum; rv = vlcurkeycache(mulcur->villa, sp); mulcur->curleaf = mulcur->villa->curleaf; mulcur->curknum = mulcur->villa->curknum; mulcur->curvnum = mulcur->villa->curvnum; mulcur->villa->curleaf = swap.curleaf; mulcur->villa->curknum = swap.curknum; mulcur->villa->curvnum = swap.curvnum; return rv; } /* Refer to volatile cache of the value of the record where a multiple cursor is. */ const char *vlmulcurvalcache(VLMULCUR *mulcur, int *sp){ VLMULCUR swap; const char *rv; assert(mulcur); swap.curleaf = mulcur->villa->curleaf; swap.curknum = mulcur->villa->curknum; swap.curvnum = mulcur->villa->curvnum; mulcur->villa->curleaf = mulcur->curleaf; mulcur->villa->curknum = mulcur->curknum; mulcur->villa->curvnum = mulcur->curvnum; rv = vlcurvalcache(mulcur->villa, sp); mulcur->curleaf = mulcur->villa->curleaf; mulcur->curknum = mulcur->villa->curknum; mulcur->curvnum = mulcur->villa->curvnum; mulcur->villa->curleaf = swap.curleaf; mulcur->villa->curknum = swap.curknum; mulcur->villa->curvnum = swap.curvnum; return rv; } /************************************************************************************************* * private objects *************************************************************************************************/ /* Compare keys of two records by lexical order. `aptr' specifies the pointer to the region of one key. `asiz' specifies the size of the region of one key. `bptr' specifies the pointer to the region of the other key. `bsiz' specifies the size of the region of the other key. The return value is positive if the former is big, negative if the latter is big, 0 if both are equivalent. */ static int vllexcompare(const char *aptr, int asiz, const char *bptr, int bsiz){ int i, min; assert(aptr && asiz >= 0 && bptr && bsiz >= 0); min = asiz < bsiz ? asiz : bsiz; for(i = 0; i < min; i++){ if(((unsigned char *)aptr)[i] != ((unsigned char *)bptr)[i]) return ((unsigned char *)aptr)[i] - ((unsigned char *)bptr)[i]; } if(asiz == bsiz) return 0; return asiz - bsiz; } /* Compare keys of two records as native integers. `aptr' specifies the pointer to the region of one key. `asiz' specifies the size of the region of one key. `bptr' specifies the pointer to the region of the other key. `bsiz' specifies the size of the region of the other key. The return value is positive if the former is big, negative if the latter is big, 0 if both are equivalent. */ static int vlintcompare(const char *aptr, int asiz, const char *bptr, int bsiz){ int anum, bnum; assert(aptr && asiz >= 0 && bptr && bsiz >= 0); if(asiz != bsiz) return asiz - bsiz; anum = (asiz == sizeof(int) ? *(int *)aptr : INT_MIN); bnum = (bsiz == sizeof(int) ? *(int *)bptr : INT_MIN); return anum - bnum; } /* Compare keys of two records as numbers of big endian. `aptr' specifies the pointer to the region of one key. `asiz' specifies the size of the region of one key. `bptr' specifies the pointer to the region of the other key. `bsiz' specifies the size of the region of the other key. The return value is positive if the former is big, negative if the latter is big, 0 if both are equivalent. */ static int vlnumcompare(const char *aptr, int asiz, const char *bptr, int bsiz){ int i; assert(aptr && asiz >= 0 && bptr && bsiz >= 0); if(asiz != bsiz) return asiz - bsiz; for(i = 0; i < asiz; i++){ if(aptr[i] != bptr[i]) return aptr[i] - bptr[i]; } return 0; } /* Compare keys of two records as numeric strings of octal, decimal or hexadecimal. `aptr' specifies the pointer to the region of one key. `asiz' specifies the size of the region of one key. `bptr' specifies the pointer to the region of the other key. `bsiz' specifies the size of the region of the other key. The return value is positive if the former is big, negative if the latter is big, 0 if both are equivalent. */ static int vldeccompare(const char *aptr, int asiz, const char *bptr, int bsiz){ assert(aptr && asiz >= 0 && bptr && bsiz >= 0); return (int)(strtod(aptr, NULL) - strtod(bptr, NULL)); } /* Store a record composed of a pair of integers. `depot' specifies an internal database handle. `knum' specifies an integer of the key. `vnum' specifies an integer of the value. The return value is true if successful, else, it is false. */ static int vldpputnum(DEPOT *depot, int knum, int vnum){ assert(depot); return dpput(depot, (char *)&knum, sizeof(int), (char *)&vnum, sizeof(int), DP_DOVER); } /* Retrieve a record composed of a pair of integers. `depot' specifies an internal database handle. `knum' specifies an integer of the key. `vip' specifies the pointer to a variable to assign the result to. The return value is true if successful, else, it is false. */ static int vldpgetnum(DEPOT *depot, int knum, int *vnp){ char *vbuf; int vsiz; assert(depot && vnp); vbuf = dpget(depot, (char *)&knum, sizeof(int), 0, -1, &vsiz); if(!vbuf || vsiz != sizeof(int)){ free(vbuf); return FALSE; } *vnp = *(int *)vbuf; free(vbuf); return TRUE; } /* Create a new leaf. `villa' specifies a database handle. `prev' specifies the ID number of the previous leaf. `next' specifies the ID number of the previous leaf. The return value is a handle of the leaf. */ static VLLEAF *vlleafnew(VILLA *villa, int prev, int next){ VLLEAF lent; assert(villa); lent.id = villa->lnum + VL_LEAFIDMIN; lent.dirty = TRUE; CB_LISTOPEN(lent.recs); lent.prev = prev; lent.next = next; villa->lnum++; cbmapput(villa->leafc, (char *)&(lent.id), sizeof(int), (char *)&lent, sizeof(VLLEAF), TRUE); return (VLLEAF *)cbmapget(villa->leafc, (char *)&(lent.id), sizeof(int), NULL); } /* Remove a leaf from the cache. `villa' specifies a database handle. `id' specifies the ID number of the leaf. The return value is true if successful, else, it is false. */ static int vlleafcacheout(VILLA *villa, int id){ VLLEAF *leaf; VLREC *recp; CBLIST *recs; int i, err, ln; assert(villa && id >= VL_LEAFIDMIN); if(!(leaf = (VLLEAF *)cbmapget(villa->leafc, (char *)&id, sizeof(int), NULL))) return FALSE; err = FALSE; if(leaf->dirty && !vlleafsave(villa, leaf)) err = TRUE; recs = leaf->recs; ln = CB_LISTNUM(recs); for(i = 0; i < ln; i++){ recp = (VLREC *)CB_LISTVAL(recs, i); CB_DATUMCLOSE(recp->key); CB_DATUMCLOSE(recp->first); if(recp->rest) CB_LISTCLOSE(recp->rest); } CB_LISTCLOSE(recs); cbmapout(villa->leafc, (char *)&id, sizeof(int)); return err ? FALSE : TRUE; } /* Save a leaf into the database. `villa' specifies a database handle. `leaf' specifies a leaf handle. The return value is true if successful, else, it is false. */ static int vlleafsave(VILLA *villa, VLLEAF *leaf){ VLREC *recp; CBLIST *recs; CBDATUM *buf; char vnumbuf[VL_VNUMBUFSIZ], *zbuf; const char *vbuf; int i, j, ksiz, vnum, vsiz, prev, next, vnumsiz, ln, zsiz; assert(villa && leaf); CB_DATUMOPEN(buf); prev = leaf->prev; if(prev == -1) prev = VL_NODEIDMIN - 1; VL_SETVNUMBUF(vnumsiz, vnumbuf, prev); CB_DATUMCAT(buf, vnumbuf, vnumsiz); next = leaf->next; if(next == -1) next = VL_NODEIDMIN - 1; VL_SETVNUMBUF(vnumsiz, vnumbuf, next); CB_DATUMCAT(buf, vnumbuf, vnumsiz); recs = leaf->recs; ln = CB_LISTNUM(recs); for(i = 0; i < ln; i++){ recp = (VLREC *)CB_LISTVAL(recs, i); ksiz = CB_DATUMSIZE(recp->key); VL_SETVNUMBUF(vnumsiz, vnumbuf, ksiz); CB_DATUMCAT(buf, vnumbuf, vnumsiz); CB_DATUMCAT(buf, CB_DATUMPTR(recp->key), ksiz); vnum = 1 + (recp->rest ? CB_LISTNUM(recp->rest) : 0); VL_SETVNUMBUF(vnumsiz, vnumbuf, vnum); CB_DATUMCAT(buf, vnumbuf, vnumsiz); vsiz = CB_DATUMSIZE(recp->first); VL_SETVNUMBUF(vnumsiz, vnumbuf, vsiz); CB_DATUMCAT(buf, vnumbuf, vnumsiz); CB_DATUMCAT(buf, CB_DATUMPTR(recp->first), vsiz); if(recp->rest){ for(j = 0; j < CB_LISTNUM(recp->rest); j++){ vbuf = CB_LISTVAL2(recp->rest, j, vsiz); VL_SETVNUMBUF(vnumsiz, vnumbuf, vsiz); CB_DATUMCAT(buf, vnumbuf, vnumsiz); CB_DATUMCAT(buf, vbuf, vsiz); } } } if(_qdbm_deflate && villa->cmode == VL_OZCOMP){ if(!(zbuf = _qdbm_deflate(CB_DATUMPTR(buf), CB_DATUMSIZE(buf), &zsiz, _QDBM_ZMRAW))){ CB_DATUMCLOSE(buf); dpecodeset(DP_EMISC, __FILE__, __LINE__); return FALSE; } if(!dpput(villa->depot, (char *)&(leaf->id), sizeof(int), zbuf, zsiz, DP_DOVER)){ CB_DATUMCLOSE(buf); dpecodeset(DP_EBROKEN, __FILE__, __LINE__); return FALSE; } free(zbuf); } else if(_qdbm_lzoencode && villa->cmode == VL_OYCOMP){ if(!(zbuf = _qdbm_lzoencode(CB_DATUMPTR(buf), CB_DATUMSIZE(buf), &zsiz))){ CB_DATUMCLOSE(buf); dpecodeset(DP_EMISC, __FILE__, __LINE__); return FALSE; } if(!dpput(villa->depot, (char *)&(leaf->id), sizeof(int), zbuf, zsiz, DP_DOVER)){ CB_DATUMCLOSE(buf); dpecodeset(DP_EBROKEN, __FILE__, __LINE__); return FALSE; } free(zbuf); } else if(_qdbm_bzencode && villa->cmode == VL_OXCOMP){ if(!(zbuf = _qdbm_bzencode(CB_DATUMPTR(buf), CB_DATUMSIZE(buf), &zsiz))){ CB_DATUMCLOSE(buf); dpecodeset(DP_EMISC, __FILE__, __LINE__); return FALSE; } if(!dpput(villa->depot, (char *)&(leaf->id), sizeof(int), zbuf, zsiz, DP_DOVER)){ CB_DATUMCLOSE(buf); dpecodeset(DP_EBROKEN, __FILE__, __LINE__); return FALSE; } free(zbuf); } else { if(!dpput(villa->depot, (char *)&(leaf->id), sizeof(int), CB_DATUMPTR(buf), CB_DATUMSIZE(buf), DP_DOVER)){ CB_DATUMCLOSE(buf); dpecodeset(DP_EBROKEN, __FILE__, __LINE__); return FALSE; } } CB_DATUMCLOSE(buf); leaf->dirty = FALSE; return TRUE; } /* Load a leaf from the database. `villa' specifies a database handle. `id' specifies the ID number of the leaf. If successful, the return value is the pointer to the leaf, else, it is `NULL'. */ static VLLEAF *vlleafload(VILLA *villa, int id){ char wbuf[VL_PAGEBUFSIZ], *buf, *rp, *kbuf, *vbuf, *zbuf; int i, size, step, ksiz, vnum, vsiz, prev, next, zsiz; VLLEAF *leaf, lent; VLREC rec; assert(villa && id >= VL_LEAFIDMIN); if((leaf = (VLLEAF *)cbmapget(villa->leafc, (char *)&id, sizeof(int), NULL)) != NULL){ cbmapmove(villa->leafc, (char *)&id, sizeof(int), FALSE); return leaf; } ksiz = -1; prev = -1; next = -1; if((size = dpgetwb(villa->depot, (char *)&id, sizeof(int), 0, VL_PAGEBUFSIZ, wbuf)) > 0 && size < VL_PAGEBUFSIZ){ buf = NULL; } else if(!(buf = dpget(villa->depot, (char *)&id, sizeof(int), 0, -1, &size))){ dpecodeset(DP_EBROKEN, __FILE__, __LINE__); return NULL; } if(_qdbm_inflate && villa->cmode == VL_OZCOMP){ if(!(zbuf = _qdbm_inflate(buf ? buf : wbuf, size, &zsiz, _QDBM_ZMRAW))){ dpecodeset(DP_EBROKEN, __FILE__, __LINE__); free(buf); return NULL; } free(buf); buf = zbuf; size = zsiz; } else if(_qdbm_lzodecode && villa->cmode == VL_OYCOMP){ if(!(zbuf = _qdbm_lzodecode(buf ? buf : wbuf, size, &zsiz))){ dpecodeset(DP_EBROKEN, __FILE__, __LINE__); free(buf); return NULL; } free(buf); buf = zbuf; size = zsiz; } else if(_qdbm_bzdecode && villa->cmode == VL_OXCOMP){ if(!(zbuf = _qdbm_bzdecode(buf ? buf : wbuf, size, &zsiz))){ dpecodeset(DP_EBROKEN, __FILE__, __LINE__); free(buf); return NULL; } free(buf); buf = zbuf; size = zsiz; } rp = buf ? buf : wbuf; if(size >= 1){ VL_READVNUMBUF(rp, size, prev, step); rp += step; size -= step; if(prev >= VL_NODEIDMIN - 1) prev = -1; } if(size >= 1){ VL_READVNUMBUF(rp, size, next, step); rp += step; size -= step; if(next >= VL_NODEIDMIN - 1) next = -1; } lent.id = id; lent.dirty = FALSE; CB_LISTOPEN(lent.recs); lent.prev = prev; lent.next = next; while(size >= 1){ VL_READVNUMBUF(rp, size, ksiz, step); rp += step; size -= step; if(size < ksiz) break; kbuf = rp; rp += ksiz; size -= ksiz; VL_READVNUMBUF(rp, size, vnum, step); rp += step; size -= step; if(vnum < 1 || size < 1) break; for(i = 0; i < vnum && size >= 1; i++){ VL_READVNUMBUF(rp, size, vsiz, step); rp += step; size -= step; if(size < vsiz) break; vbuf = rp; rp += vsiz; size -= vsiz; if(i < 1){ CB_DATUMOPEN2(rec.key, kbuf, ksiz); CB_DATUMOPEN2(rec.first, vbuf, vsiz); rec.rest = NULL; } else { if(!rec.rest) CB_LISTOPEN(rec.rest); CB_LISTPUSH(rec.rest, vbuf, vsiz); } } if(i > 0) CB_LISTPUSH(lent.recs, (char *)&rec, sizeof(VLREC)); } free(buf); cbmapput(villa->leafc, (char *)&(lent.id), sizeof(int), (char *)&lent, sizeof(VLLEAF), TRUE); return (VLLEAF *)cbmapget(villa->leafc, (char *)&(lent.id), sizeof(int), NULL); } /* Load the historical leaf from the database. `villa' specifies a database handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If successful, the return value is the pointer to the leaf, else, it is `NULL'. */ static VLLEAF *vlgethistleaf(VILLA *villa, const char *kbuf, int ksiz){ VLLEAF *leaf; VLREC *recp; int ln, rv; assert(villa && kbuf && ksiz >= 0); if(!(leaf = vlleafload(villa, villa->hleaf))) return NULL; if((ln = CB_LISTNUM(leaf->recs)) < 2) return NULL; recp = (VLREC *)CB_LISTVAL(leaf->recs, 0); rv = villa->cmp(kbuf, ksiz, CB_DATUMPTR(recp->key), CB_DATUMSIZE(recp->key)); if(rv == 0) return leaf; if(rv < 0) return NULL; recp = (VLREC *)CB_LISTVAL(leaf->recs, ln - 1); rv = villa->cmp(kbuf, ksiz, CB_DATUMPTR(recp->key), CB_DATUMSIZE(recp->key)); if(rv <= 0 || leaf->next < VL_LEAFIDMIN) return leaf; return NULL; } /* Add a record to a leaf. `villa' specifies a database handle. `leaf' specifies a leaf handle. `dmode' specifies behavior when the key overlaps. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. `vbuf' specifies the pointer to the region of a value. `vsiz' specifies the size of the region of the value. The return value is true if successful, else, it is false. */ static int vlleafaddrec(VILLA *villa, VLLEAF *leaf, int dmode, const char *kbuf, int ksiz, const char *vbuf, int vsiz){ VLREC *recp, rec; CBLIST *recs; int i, rv, left, right, ln, tsiz; char *tbuf; assert(villa && leaf && kbuf && ksiz >= 0 && vbuf && vsiz >= 0); left = 0; recs = leaf->recs; ln = CB_LISTNUM(recs); right = ln; i = (left + right) / 2; while(right >= left && i < ln){ recp = (VLREC *)CB_LISTVAL(recs, i); rv = villa->cmp(kbuf, ksiz, CB_DATUMPTR(recp->key), CB_DATUMSIZE(recp->key)); if(rv == 0){ break; } else if(rv <= 0){ right = i - 1; } else { left = i + 1; } i = (left + right) / 2; } while(i < ln){ recp = (VLREC *)CB_LISTVAL(recs, i); rv = villa->cmp(kbuf, ksiz, CB_DATUMPTR(recp->key), CB_DATUMSIZE(recp->key)); if(rv == 0){ switch(dmode){ case VL_DKEEP: return FALSE; case VL_DCAT: CB_DATUMCAT(recp->first, vbuf, vsiz); break; case VL_DDUP: if(!recp->rest) CB_LISTOPEN(recp->rest); CB_LISTPUSH(recp->rest, vbuf, vsiz); villa->rnum++; break; case VL_DDUPR: if(!recp->rest){ CB_DATUMTOMALLOC(recp->first, tbuf, tsiz); CB_DATUMOPEN2(recp->first, vbuf, vsiz); CB_LISTOPEN(recp->rest); CB_LISTPUSHBUF(recp->rest, tbuf, tsiz); } else { cblistunshift(recp->rest, CB_DATUMPTR(recp->first), CB_DATUMSIZE(recp->first)); CB_DATUMSETSIZE(recp->first, 0); CB_DATUMCAT(recp->first, vbuf, vsiz); } villa->rnum++; break; default: CB_DATUMSETSIZE(recp->first, 0); CB_DATUMCAT(recp->first, vbuf, vsiz); break; } break; } else if(rv < 0){ CB_DATUMOPEN2(rec.key, kbuf, ksiz); CB_DATUMOPEN2(rec.first, vbuf, vsiz); rec.rest = NULL; CB_LISTINSERT(recs, i, (char *)&rec, sizeof(VLREC)); villa->rnum++; break; } i++; } if(i >= ln){ CB_DATUMOPEN2(rec.key, kbuf, ksiz); CB_DATUMOPEN2(rec.first, vbuf, vsiz); rec.rest = NULL; CB_LISTPUSH(recs, (char *)&rec, sizeof(VLREC)); villa->rnum++; } leaf->dirty = TRUE; return TRUE; } /* Calculate the size of data of a leaf. `leaf' specifies a leaf handle. The return value is size of data of the leaf. */ static int vlleafdatasize(VLLEAF *leaf){ VLREC *recp; CBLIST *recs, *rest; const char *vbuf; int i, j, sum, rnum, restnum, vsiz; assert(leaf); sum = 0; recs = leaf->recs; rnum = CB_LISTNUM(recs); for(i = 0; i < rnum; i++){ recp = (VLREC *)CB_LISTVAL(recs, i); sum += CB_DATUMSIZE(recp->key); sum += CB_DATUMSIZE(recp->first); if(recp->rest){ rest = recp->rest; restnum = CB_LISTNUM(rest); for(j = 0; j < restnum; j++){ vbuf = CB_LISTVAL2(rest, j, vsiz); sum += vsiz; } } } return sum; } /* Divide a leaf into two. `villa' specifies a database handle. `leaf' specifies a leaf handle. The return value is the handle of a new leaf, or `NULL' on failure. */ static VLLEAF *vlleafdivide(VILLA *villa, VLLEAF *leaf){ VLLEAF *newleaf, *nextleaf; VLREC *recp; CBLIST *recs, *newrecs; int i, mid, ln; assert(villa && leaf); villa->hleaf = -1; recs = leaf->recs; mid = CB_LISTNUM(recs) / 2; recp = (VLREC *)CB_LISTVAL(recs, mid); newleaf = vlleafnew(villa, leaf->id, leaf->next); if(newleaf->next != -1){ if(!(nextleaf = vlleafload(villa, newleaf->next))) return NULL; nextleaf->prev = newleaf->id; nextleaf->dirty = TRUE; } leaf->next = newleaf->id; leaf->dirty = TRUE; ln = CB_LISTNUM(recs); newrecs = newleaf->recs; for(i = mid; i < ln; i++){ recp = (VLREC *)CB_LISTVAL(recs, i); CB_LISTPUSH(newrecs, (char *)recp, sizeof(VLREC)); } ln = CB_LISTNUM(newrecs); for(i = 0; i < ln; i++){ CB_LISTDROP(recs); } return newleaf; } /* Create a new node. `villa' specifies a database handle. `heir' specifies the ID of the child before the first index. The return value is a handle of the node. */ static VLNODE *vlnodenew(VILLA *villa, int heir){ VLNODE nent; assert(villa && heir >= VL_LEAFIDMIN); nent.id = villa->nnum + VL_NODEIDMIN; nent.dirty = TRUE; nent.heir = heir; CB_LISTOPEN(nent.idxs); villa->nnum++; cbmapput(villa->nodec, (char *)&(nent.id), sizeof(int), (char *)&nent, sizeof(VLNODE), TRUE); return (VLNODE *)cbmapget(villa->nodec, (char *)&(nent.id), sizeof(int), NULL); } /* Remove a node from the cache. `villa' specifies a database handle. `id' specifies the ID number of the node. The return value is true if successful, else, it is false. */ static int vlnodecacheout(VILLA *villa, int id){ VLNODE *node; VLIDX *idxp; int i, err, ln; assert(villa && id >= VL_NODEIDMIN); if(!(node = (VLNODE *)cbmapget(villa->nodec, (char *)&id, sizeof(int), NULL))) return FALSE; err = FALSE; if(node->dirty && !vlnodesave(villa, node)) err = TRUE; ln = CB_LISTNUM(node->idxs); for(i = 0; i < ln; i++){ idxp = (VLIDX *)CB_LISTVAL(node->idxs, i); CB_DATUMCLOSE(idxp->key); } CB_LISTCLOSE(node->idxs); cbmapout(villa->nodec, (char *)&id, sizeof(int)); return err ? FALSE : TRUE; } /* Save a node into the database. `villa' specifies a database handle. `node' specifies a node handle. The return value is true if successful, else, it is false. */ static int vlnodesave(VILLA *villa, VLNODE *node){ CBDATUM *buf; char vnumbuf[VL_VNUMBUFSIZ]; VLIDX *idxp; int i, heir, pid, ksiz, vnumsiz, ln; assert(villa && node); CB_DATUMOPEN(buf); heir = node->heir; VL_SETVNUMBUF(vnumsiz, vnumbuf, heir); CB_DATUMCAT(buf, vnumbuf, vnumsiz); ln = CB_LISTNUM(node->idxs); for(i = 0; i < ln; i++){ idxp = (VLIDX *)CB_LISTVAL(node->idxs, i); pid = idxp->pid; VL_SETVNUMBUF(vnumsiz, vnumbuf, pid); CB_DATUMCAT(buf, vnumbuf, vnumsiz); ksiz = CB_DATUMSIZE(idxp->key); VL_SETVNUMBUF(vnumsiz, vnumbuf, ksiz); CB_DATUMCAT(buf, vnumbuf, vnumsiz); CB_DATUMCAT(buf, CB_DATUMPTR(idxp->key), ksiz); } if(!dpput(villa->depot, (char *)&(node->id), sizeof(int), CB_DATUMPTR(buf), CB_DATUMSIZE(buf), DP_DOVER)){ CB_DATUMCLOSE(buf); dpecodeset(DP_EBROKEN, __FILE__, __LINE__); return FALSE; } CB_DATUMCLOSE(buf); node->dirty = FALSE; return TRUE; } /* Load a node from the database. `villa' specifies a database handle. `id' specifies the ID number of the node. If successful, the return value is the pointer to the node, else, it is `NULL'. */ static VLNODE *vlnodeload(VILLA *villa, int id){ char wbuf[VL_PAGEBUFSIZ], *buf, *rp, *kbuf; int size, step, heir, pid, ksiz; VLNODE *node, nent; VLIDX idx; assert(villa && id >= VL_NODEIDMIN); if((node = (VLNODE *)cbmapget(villa->nodec, (char *)&id, sizeof(int), NULL)) != NULL){ cbmapmove(villa->nodec, (char *)&id, sizeof(int), FALSE); return node; } heir = -1; if((size = dpgetwb(villa->depot, (char *)&id, sizeof(int), 0, VL_PAGEBUFSIZ, wbuf)) > 0 && size < VL_PAGEBUFSIZ){ buf = NULL; } else if(!(buf = dpget(villa->depot, (char *)&id, sizeof(int), 0, -1, &size))){ dpecodeset(DP_EBROKEN, __FILE__, __LINE__); return NULL; } rp = buf ? buf : wbuf; if(size >= 1){ VL_READVNUMBUF(rp, size, heir, step); rp += step; size -= step; } if(heir < 0){ free(buf); return NULL; } nent.id = id; nent.dirty = FALSE; nent.heir = heir; CB_LISTOPEN(nent.idxs); while(size >= 1){ VL_READVNUMBUF(rp, size, pid, step); rp += step; size -= step; if(size < 1) break; VL_READVNUMBUF(rp, size, ksiz, step); rp += step; size -= step; if(size < ksiz) break; kbuf = rp; rp += ksiz; size -= ksiz; idx.pid = pid; CB_DATUMOPEN2(idx.key, kbuf, ksiz); CB_LISTPUSH(nent.idxs, (char *)&idx, sizeof(VLIDX)); } free(buf); cbmapput(villa->nodec, (char *)&(nent.id), sizeof(int), (char *)&nent, sizeof(VLNODE), TRUE); return (VLNODE *)cbmapget(villa->nodec, (char *)&(nent.id), sizeof(int), NULL); } /* Add an index to a node. `villa' specifies a database handle. `node' specifies a node handle. `order' specifies whether the calling sequence is orderd or not. `pid' specifies the ID number of referred page. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. */ static void vlnodeaddidx(VILLA *villa, VLNODE *node, int order, int pid, const char *kbuf, int ksiz){ VLIDX idx, *idxp; int i, rv, left, right, ln; assert(villa && node && pid >= VL_LEAFIDMIN && kbuf && ksiz >= 0); idx.pid = pid; CB_DATUMOPEN2(idx.key, kbuf, ksiz); if(order){ CB_LISTPUSH(node->idxs, (char *)&idx, sizeof(VLIDX)); } else { left = 0; right = CB_LISTNUM(node->idxs); i = (left + right) / 2; ln = CB_LISTNUM(node->idxs); while(right >= left && i < ln){ idxp = (VLIDX *)CB_LISTVAL(node->idxs, i); rv = villa->cmp(kbuf, ksiz, CB_DATUMPTR(idxp->key), CB_DATUMSIZE(idxp->key)); if(rv == 0){ break; } else if(rv <= 0){ right = i - 1; } else { left = i + 1; } i = (left + right) / 2; } ln = CB_LISTNUM(node->idxs); while(i < ln){ idxp = (VLIDX *)CB_LISTVAL(node->idxs, i); if(villa->cmp(kbuf, ksiz, CB_DATUMPTR(idxp->key), CB_DATUMSIZE(idxp->key)) < 0){ CB_LISTINSERT(node->idxs, i, (char *)&idx, sizeof(VLIDX)); break; } i++; } if(i >= CB_LISTNUM(node->idxs)) CB_LISTPUSH(node->idxs, (char *)&idx, sizeof(VLIDX)); } node->dirty = TRUE; } /* Search the leaf corresponding to a key. `villa' specifies a database handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. The return value is the ID number of the leaf, or -1 on failure. */ static int vlsearchleaf(VILLA *villa, const char *kbuf, int ksiz){ VLNODE *node; VLIDX *idxp; int i, pid, rv, left, right, ln; assert(villa && kbuf && ksiz >= 0); pid = villa->root; idxp = NULL; villa->hnum = 0; villa->hleaf = -1; while(pid >= VL_NODEIDMIN){ if(!(node = vlnodeload(villa, pid)) || (ln = CB_LISTNUM(node->idxs)) < 1){ dpecodeset(DP_EBROKEN, __FILE__, __LINE__); return -1; } villa->hist[villa->hnum++] = node->id; left = 1; right = ln; i = (left + right) / 2; while(right >= left && i < ln){ idxp = (VLIDX *)CB_LISTVAL(node->idxs, i); rv = villa->cmp(kbuf, ksiz, CB_DATUMPTR(idxp->key), CB_DATUMSIZE(idxp->key)); if(rv == 0){ break; } else if(rv <= 0){ right = i - 1; } else { left = i + 1; } i = (left + right) / 2; } if(i > 0) i--; while(i < ln){ idxp = (VLIDX *)CB_LISTVAL(node->idxs, i); if(villa->cmp(kbuf, ksiz, CB_DATUMPTR(idxp->key), CB_DATUMSIZE(idxp->key)) < 0){ if(i == 0){ pid = node->heir; break; } idxp = (VLIDX *)CB_LISTVAL(node->idxs, i - 1); pid = idxp->pid; break; } i++; } if(i >= ln) pid = idxp->pid; } if(villa->lleaf == pid) villa->hleaf = pid; villa->lleaf = pid; return pid; } /* Adjust the caches for leaves and nodes. `villa' specifies a database handle. The return value is true if successful, else, it is false. */ static int vlcacheadjust(VILLA *villa){ const char *tmp; int i, pid, err; err = FALSE; if(cbmaprnum(villa->leafc) > villa->leafcnum){ cbmapiterinit(villa->leafc); for(i = 0; i < VL_CACHEOUT; i++){ tmp = cbmapiternext(villa->leafc, NULL); pid = *(int *)tmp; if(!vlleafcacheout(villa, pid)) err = TRUE; } } if(cbmaprnum(villa->nodec) > villa->nodecnum){ cbmapiterinit(villa->nodec); for(i = 0; i < VL_CACHEOUT; i++){ tmp = cbmapiternext(villa->nodec, NULL); pid = *(int *)tmp; if(!vlnodecacheout(villa, pid)) err = TRUE; } } return err ? FALSE : TRUE; } /* Search a record of a leaf. `villa' specifies a database handle. `leaf' specifies a leaf handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. `ip' specifies the pointer to a variable to fetch the index of the correspnding record. The return value is the pointer to a corresponding record, or `NULL' on failure. */ static VLREC *vlrecsearch(VILLA *villa, VLLEAF *leaf, const char *kbuf, int ksiz, int *ip){ VLREC *recp; CBLIST *recs; int i, rv, left, right, ln; assert(villa && leaf && kbuf && ksiz >= 0); recs = leaf->recs; ln = CB_LISTNUM(recs); left = 0; right = ln; i = (left + right) / 2; while(right >= left && i < ln){ recp = (VLREC *)CB_LISTVAL(recs, i); rv = villa->cmp(kbuf, ksiz, CB_DATUMPTR(recp->key), CB_DATUMSIZE(recp->key)); if(rv == 0){ if(ip) *ip = i; return recp; } else if(rv <= 0){ right = i - 1; } else { left = i + 1; } i = (left + right) / 2; } if(ip) *ip = i; return NULL; } /* Get flags of a database. */ int vlgetflags(VILLA *villa){ assert(villa); return dpgetflags(villa->depot); } /* Set flags of a database. `villa' specifies a database handle connected as a writer. `flags' specifies flags to set. Lesser ten bits are reserved for internal use. If successful, the return value is true, else, it is false. */ int vlsetflags(VILLA *villa, int flags){ assert(villa); if(!villa->wmode){ dpecodeset(DP_EMODE, __FILE__, __LINE__); return FALSE; } return dpsetflags(villa->depot, flags); } /* END OF FILE */ qdbm-1.8.78/crtsv.c0000644000175000017500000001461010610627747013065 0ustar mikiomikio/************************************************************************************************* * Mutual converter between a database of Curia and a TSV text * Copyright (C) 2000-2007 Mikio Hirabayashi * This file is part of QDBM, Quick Database Manager. * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU * Lesser General Public License as published by the Free Software Foundation; either version * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * You should have received a copy of the GNU Lesser General Public License along with QDBM; if * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. *************************************************************************************************/ #include #include #include #include #include #include #undef TRUE #define TRUE 1 /* boolean true */ #undef FALSE #define FALSE 0 /* boolean false */ /* for RISC OS */ #if defined(__riscos__) || defined(__riscos) #include int __riscosify_control = __RISCOSIFY_NO_PROCESS; #endif /* global variables */ const char *progname; /* program name */ /* function prototypes */ int main(int argc, char **argv); void usage(void); int runimport(int argc, char **argv); int runexport(int argc, char **argv); void pdperror(const char *name); char *getl(void); int doimport(const char *name, int bnum, int dnum, int bin); int doexport(const char *name, int bin); /* main routine */ int main(int argc, char **argv){ int rv; cbstdiobin(); progname = argv[0]; if(argc < 2) usage(); rv = 0; if(!strcmp(argv[1], "import")){ rv = runimport(argc, argv); } else if(!strcmp(argv[1], "export")){ rv = runexport(argc, argv); } else { usage(); } return rv; } /* print the usage and exit */ void usage(void){ fprintf(stderr, "%s: mutual converter between TSV and Curia database\n", progname); fprintf(stderr, "\n"); fprintf(stderr, "usage:\n"); fprintf(stderr, " %s import [-bnum num] [-dnum num] [-bin] name\n", progname); fprintf(stderr, " %s export [-bin] name\n", progname); fprintf(stderr, "\n"); exit(1); } /* parse arguments of import command */ int runimport(int argc, char **argv){ char *name; int i, bnum, dnum, bin, rv; name = NULL; bnum = -1; dnum = -1; bin = FALSE; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ if(!strcmp(argv[i], "-bnum")){ if(++i >= argc) usage(); bnum = atoi(argv[i]); } else if(!strcmp(argv[i], "-dnum")){ if(++i >= argc) usage(); dnum = atoi(argv[i]); } else if(!strcmp(argv[i], "-bin")){ bin = TRUE; } else { usage(); } } else if(!name){ name = argv[i]; } else { usage(); } } if(!name) usage(); rv = doimport(name, bnum, dnum, bin); return rv; } /* parse arguments of export command */ int runexport(int argc, char **argv){ char *name; int i, bin, rv; name = NULL; bin = FALSE; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ if(!strcmp(argv[i], "-bin")){ bin = TRUE; } else { usage(); } } else if(!name){ name = argv[i]; } else { usage(); } } if(!name) usage(); rv = doexport(name, bin); return rv; } /* print an error message */ void pdperror(const char *name){ fprintf(stderr, "%s: %s: %s\n", progname, name, dperrmsg(dpecode)); } /* read a line */ char *getl(void){ char *buf; int c, len, blen; buf = NULL; len = 0; blen = 256; while((c = getchar()) != EOF){ if(blen <= len) blen *= 2; buf = cbrealloc(buf, blen + 1); if(c == '\n') c = '\0'; buf[len++] = c; if(c == '\0') break; } if(!buf) return NULL; buf[len] = '\0'; return buf; } /* perform import command */ int doimport(const char *name, int bnum, int dnum, int bin){ CURIA *curia; char *buf, *kbuf, *vbuf, *ktmp, *vtmp; int i, err, ktsiz, vtsiz; /* open a database */ if(!(curia = cropen(name, CR_OWRITER | CR_OCREAT, bnum, dnum))){ pdperror(name); return 1; } /* loop for each line */ err = FALSE; for(i = 1; (buf = getl()) != NULL; i++){ kbuf = buf; if((vbuf = strchr(buf, '\t')) != NULL){ *vbuf = '\0'; vbuf++; /* store a record */ if(bin){ ktmp = cbbasedecode(kbuf, &ktsiz); vtmp = cbbasedecode(vbuf, &vtsiz); if(!crput(curia, ktmp, ktsiz, vtmp, vtsiz, CR_DOVER)){ pdperror(name); err = TRUE; } free(vtmp); free(ktmp); } else { if(!crput(curia, kbuf, -1, vbuf, -1, CR_DOVER)){ pdperror(name); err = TRUE; } } } else { fprintf(stderr, "%s: %s: invalid format in line %d\n", progname, name, i); } free(buf); if(err) break; } /* close the database */ if(!crclose(curia)){ pdperror(name); return 1; } return err ? 1 : 0; } /* perform export command */ int doexport(const char *name, int bin){ CURIA *curia; char *kbuf, *vbuf, *tmp; int err, ksiz, vsiz; /* open a database */ if(!(curia = cropen(name, CR_OREADER, -1, -1))){ pdperror(name); return 1; } /* initialize the iterator */ criterinit(curia); /* loop for each key */ err = FALSE; while((kbuf = criternext(curia, &ksiz)) != NULL){ /* retrieve a value with a key */ if(!(vbuf = crget(curia, kbuf, ksiz, 0, -1, &vsiz))){ pdperror(name); free(kbuf); err = TRUE; break; } /* output data */ if(bin){ tmp = cbbaseencode(kbuf, ksiz); printf("%s\t", tmp); free(tmp); tmp = cbbaseencode(vbuf, vsiz); printf("%s\n", tmp); free(tmp); } else { printf("%s\t%s\n", kbuf, vbuf); } /* free resources */ free(vbuf); free(kbuf); } /* check whether all records were retrieved */ if(dpecode != DP_ENOITEM){ pdperror(name); err = TRUE; } /* close the database */ if(!crclose(curia)){ pdperror(name); return 1; } return err ? 1 : 0; } /* END OF FILE */ qdbm-1.8.78/vltest.c0000644000175000017500000012001110610630116013216 0ustar mikiomikio/************************************************************************************************* * Test cases of Villa * Copyright (C) 2000-2007 Mikio Hirabayashi * This file is part of QDBM, Quick Database Manager. * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU * Lesser General Public License as published by the Free Software Foundation; either version * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * You should have received a copy of the GNU Lesser General Public License along with QDBM; if * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. *************************************************************************************************/ #include #include #include #include #include #include #include #include #include #undef TRUE #define TRUE 1 /* boolean true */ #undef FALSE #define FALSE 0 /* boolean false */ #define RECBUFSIZ 32 /* buffer for records */ /* for RISC OS */ #if defined(__riscos__) || defined(__riscos) #include int __riscosify_control = __RISCOSIFY_NO_PROCESS; #endif /* global variables */ const char *progname; /* program name */ /* function prototypes */ int main(int argc, char **argv); void usage(void); int runwrite(int argc, char **argv); int runread(int argc, char **argv); int runrdup(int argc, char **argv); int runcombo(int argc, char **argv); int runwicked(int argc, char **argv); int printfflush(const char *format, ...); void pdperror(const char *name); int myrand(void); int dowrite(const char *name, int rnum, int ii, int cmode, int lrecmax, int nidxmax, int lcnum, int ncnum, int fbp); int doread(const char *name, int ii, int vc); int dordup(const char *name, int rnum, int pnum, int ii, int cmode, int cc, int lrecmax, int nidxmax, int lcnum, int ncnum, int fbp); int docombo(const char *name, int cmode); int dowicked(const char *name, int rnum, int cb, int cmode); /* main routine */ int main(int argc, char **argv){ char *env; int rv; cbstdiobin(); if((env = getenv("QDBMDBGFD")) != NULL) dpdbgfd = atoi(env); progname = argv[0]; if(argc < 2) usage(); rv = 0; if(!strcmp(argv[1], "write")){ rv = runwrite(argc, argv); } else if(!strcmp(argv[1], "read")){ rv = runread(argc, argv); } else if(!strcmp(argv[1], "rdup")){ rv = runrdup(argc, argv); } else if(!strcmp(argv[1], "combo")){ rv = runcombo(argc, argv); } else if(!strcmp(argv[1], "wicked")){ rv = runwicked(argc, argv); } else { usage(); } return rv; } /* print the usage and exit */ void usage(void){ fprintf(stderr, "%s: test cases for Villa\n", progname); fprintf(stderr, "\n"); fprintf(stderr, "usage:\n"); fprintf(stderr, " %s write [-int] [-cz|-cy|-cx] [-tune lrecmax nidxmax lcnum ncnum]" " [-fbp num] name rnum\n", progname); fprintf(stderr, " %s read [-int] [-vc] name\n", progname); fprintf(stderr, " %s rdup [-int] [-cz|-cy|-cx] [-cc] [-tune lrecmax nidxmax lcnum ncnum]" " [-fbp num] name rnum pnum\n", progname); fprintf(stderr, " %s combo [-cz|-cy|-cx] name\n", progname); fprintf(stderr, " %s wicked [-c] [-cz|-cy|-cx] name rnum\n", progname); fprintf(stderr, "\n"); exit(1); } /* parse arguments of write command */ int runwrite(int argc, char **argv){ char *name, *rstr; int i, rnum, ii, cmode, lrecmax, nidxmax, lcnum, ncnum, fbp, rv; name = NULL; rstr = NULL; rnum = 0; ii = FALSE; cmode = 0; lrecmax = -1; nidxmax = -1; lcnum = -1; ncnum = -1; fbp = -1; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ if(!strcmp(argv[i], "-int")){ ii = TRUE; } else if(!strcmp(argv[i], "-cz")){ cmode |= VL_OZCOMP; } else if(!strcmp(argv[i], "-cy")){ cmode |= VL_OYCOMP; } else if(!strcmp(argv[i], "-cx")){ cmode |= VL_OXCOMP; } else if(!strcmp(argv[i], "-tune")){ if(++i >= argc) usage(); lrecmax = atoi(argv[i]); if(++i >= argc) usage(); nidxmax = atoi(argv[i]); if(++i >= argc) usage(); lcnum = atoi(argv[i]); if(++i >= argc) usage(); ncnum = atoi(argv[i]); } else if(!strcmp(argv[i], "-fbp")){ if(++i >= argc) usage(); fbp = atoi(argv[i]); } else { usage(); } } else if(!name){ name = argv[i]; } else if(!rstr){ rstr = argv[i]; } else { usage(); } } if(!name || !rstr) usage(); rnum = atoi(rstr); if(rnum < 1) usage(); rv = dowrite(name, rnum, ii, cmode, lrecmax, nidxmax, lcnum, ncnum, fbp); return rv; } /* parse arguments of read command */ int runread(int argc, char **argv){ char *name; int i, ii, vc, rv; name = NULL; ii = FALSE; vc = FALSE; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ if(!strcmp(argv[i], "-int")){ ii = TRUE; } else if(!strcmp(argv[i], "-vc")){ vc = TRUE; } else { usage(); } } else if(!name){ name = argv[i]; } else { usage(); } } if(!name) usage(); rv = doread(name, ii, vc); return rv; } /* parse arguments of rdup command */ int runrdup(int argc, char **argv){ char *name, *rstr, *pstr; int i, rnum, pnum, ii, cmode, cc, lrecmax, nidxmax, lcnum, ncnum, fbp, rv; name = NULL; rstr = NULL; pstr = NULL; rnum = 0; pnum = 0; ii = FALSE; cmode = 0; cc = FALSE; lrecmax = -1; nidxmax = -1; lcnum = -1; ncnum = -1; fbp = -1; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ if(!strcmp(argv[i], "-int")){ ii = TRUE; } else if(!strcmp(argv[i], "-cz")){ cmode |= VL_OZCOMP; } else if(!strcmp(argv[i], "-cy")){ cmode |= VL_OYCOMP; } else if(!strcmp(argv[i], "-cx")){ cmode |= VL_OXCOMP; } else if(!strcmp(argv[i], "-cc")){ cc = TRUE; } else if(!strcmp(argv[i], "-tune")){ if(++i >= argc) usage(); lrecmax = atoi(argv[i]); if(++i >= argc) usage(); nidxmax = atoi(argv[i]); if(++i >= argc) usage(); lcnum = atoi(argv[i]); if(++i >= argc) usage(); ncnum = atoi(argv[i]); } else if(!strcmp(argv[i], "-fbp")){ if(++i >= argc) usage(); fbp = atoi(argv[i]); } else { usage(); } } else if(!name){ name = argv[i]; } else if(!rstr){ rstr = argv[i]; } else if(!pstr){ pstr = argv[i]; } else { usage(); } } if(!name || !rstr || !pstr) usage(); rnum = atoi(rstr); pnum = atoi(pstr); if(rnum < 1 || pnum < 1) usage(); rv = dordup(name, rnum, pnum, ii, cmode, cc, lrecmax, nidxmax, lcnum, ncnum, fbp); return rv; } /* parse arguments of combo command */ int runcombo(int argc, char **argv){ char *name; int i, cmode, rv; name = NULL; cmode = 0; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ if(!strcmp(argv[i], "-cz")){ cmode |= VL_OZCOMP; } else if(!strcmp(argv[i], "-cy")){ cmode |= VL_OYCOMP; } else if(!strcmp(argv[i], "-cx")){ cmode |= VL_OXCOMP; } else { usage(); } } else if(!name){ name = argv[i]; } else { usage(); } } if(!name) usage(); rv = docombo(name, cmode); return rv; } /* parse arguments of wicked command */ int runwicked(int argc, char **argv){ char *name, *rstr; int i, cb, cmode, rnum, rv; name = NULL; rstr = NULL; cb = FALSE; cmode = 0; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ if(!strcmp(argv[i], "-c")){ cb = TRUE; } else if(!strcmp(argv[i], "-cz")){ cmode |= VL_OZCOMP; } else if(!strcmp(argv[i], "-cy")){ cmode |= VL_OYCOMP; } else if(!strcmp(argv[i], "-cx")){ cmode |= VL_OXCOMP; } else { usage(); } } else if(!name){ name = argv[i]; } else if(!rstr){ rstr = argv[i]; } else { usage(); } } if(!name || !rstr) usage(); rnum = atoi(rstr); if(rnum < 1) usage(); rv = dowicked(name, rnum, cb, cmode); return rv; } /* print formatted string and flush the buffer */ int printfflush(const char *format, ...){ va_list ap; int rv; va_start(ap, format); rv = vprintf(format, ap); if(fflush(stdout) == EOF) rv = -1; va_end(ap); return rv; } /* print an error message */ void pdperror(const char *name){ fprintf(stderr, "%s: %s: %s\n", progname, name, dperrmsg(dpecode)); } /* pseudo random number generator */ int myrand(void){ static int cnt = 0; if(cnt == 0) srand(time(NULL)); return (rand() * rand() + (rand() >> (sizeof(int) * 4)) + (cnt++)) & INT_MAX; } /* perform write command */ int dowrite(const char *name, int rnum, int ii, int cmode, int lrecmax, int nidxmax, int lcnum, int ncnum, int fbp){ VILLA *villa; int i, omode, err, len; char buf[RECBUFSIZ]; printfflush("\n name=%s rnum=%d int=%d cmode=%d " "lrecmax=%d nidxmax=%d lcnum=%d ncnum=%d fbp=%d\n\n", name, rnum, ii, cmode, lrecmax, nidxmax, lcnum, ncnum, fbp); /* open a database */ omode = VL_OWRITER | VL_OCREAT | VL_OTRUNC | cmode; if(!(villa = vlopen(name, omode, ii ? VL_CMPINT : VL_CMPLEX))){ pdperror(name); return 1; } err = FALSE; /* set tuning parameters */ if(lrecmax > 0) vlsettuning(villa, lrecmax, nidxmax, lcnum, ncnum); if(fbp >= 0) vlsetfbpsiz(villa, fbp); /* loop for each record */ for(i = 1; i <= rnum; i++){ /* store a record */ if(ii){ if(!vlput(villa, (char *)&i, sizeof(int), (char *)&i, sizeof(int), VL_DOVER)){ pdperror(name); err = TRUE; break; } } else { len = sprintf(buf, "%08d", i); if(!vlput(villa, buf, len, buf, len, VL_DOVER)){ pdperror(name); err = TRUE; break; } } /* print progression */ if(rnum > 250 && i % (rnum / 250) == 0){ putchar('.'); fflush(stdout); if(i == rnum || i % (rnum / 10) == 0){ printfflush(" (%08d)\n", i); } } } /* close the database */ if(!vlclose(villa)){ pdperror(name); return 1; } if(!err) printfflush("ok\n\n"); return 0; } /* perform read command */ int doread(const char *name, int ii, int vc){ VILLA *villa; int i, rnum, err, len; const char *cval; char buf[RECBUFSIZ], *val; printfflush("\n name=%s int=%d\n\n", name, ii); /* open a database */ if(!(villa = vlopen(name, VL_OREADER, ii ? VL_CMPINT : VL_CMPLEX))){ pdperror(name); return 1; } /* get the number of records */ rnum = vlrnum(villa); err = FALSE; /* loop for each record */ for(i = 1; i <= rnum; i++){ /* retrieve a record */ if(ii){ if(vc){ if(!(cval = vlgetcache(villa, (char *)&i, sizeof(int), NULL))){ pdperror(name); err = TRUE; break; } } else { if(!(val = vlget(villa, (char *)&i, sizeof(int), NULL))){ pdperror(name); err = TRUE; break; } free(val); } } else { len = sprintf(buf, "%08d", i); if(vc){ if(!(cval = vlgetcache(villa, buf, len, NULL))){ pdperror(name); err = TRUE; break; } } else { if(!(val = vlget(villa, buf, len, NULL))){ pdperror(name); err = TRUE; break; } free(val); } } /* print progression */ if(rnum > 250 && i % (rnum / 250) == 0){ putchar('.'); fflush(stdout); if(i == rnum || i % (rnum / 10) == 0){ printfflush(" (%08d)\n", i); } } } /* close the database */ if(!vlclose(villa)){ pdperror(name); return 1; } if(!err) printfflush("ok\n\n"); return 0; } /* perform rdup command */ int dordup(const char *name, int rnum, int pnum, int ii, int cmode, int cc, int lrecmax, int nidxmax, int lcnum, int ncnum, int fbp){ VILLA *villa; int i, omode, err, dmode, vi, len; char buf[RECBUFSIZ]; printfflush("\n name=%s rnum=%d int=%d cmode=%d " "lrecmax=%d nidxmax=%d lcnum=%d ncnum=%d fbp=%d\n\n", name, rnum, ii, cmode, lrecmax, nidxmax, lcnum, ncnum, fbp); omode = VL_OWRITER | VL_OCREAT | VL_OTRUNC | cmode; if(!(villa = vlopen(name, omode, ii ? VL_CMPINT : VL_CMPLEX))){ pdperror(name); return 1; } err = FALSE; if(lrecmax > 0) vlsettuning(villa, lrecmax, nidxmax, lcnum, ncnum); if(fbp >= 0) vlsetfbpsiz(villa, fbp); for(i = 1; i <= rnum; i++){ dmode = i % 3 == 0 ? VL_DDUPR : VL_DDUP; if(cc && myrand() % 2 == 0) dmode = VL_DCAT; vi = myrand() % pnum + 1; if(ii){ if(!vlput(villa, (char *)&vi, sizeof(int), (char *)&vi, sizeof(int), dmode)){ pdperror(name); err = TRUE; break; } } else { len = sprintf(buf, "%08d", vi); if(!vlput(villa, buf, len, buf, len, dmode)){ pdperror(name); err = TRUE; break; } } if(rnum > 250 && i % (rnum / 250) == 0){ putchar('.'); fflush(stdout); if(i == rnum || i % (rnum / 10) == 0){ printfflush(" (%08d: fsiz=%d lnum=%d nnum=%d)\n", i, vlfsiz(villa), vllnum(villa), vlnnum(villa)); } } } if(!vlclose(villa)){ pdperror(name); return 1; } if(!err) printfflush("ok\n\n"); return 0; } /* perform combo command */ int docombo(const char *name, int cmode){ VILLA *villa; VLMULCUR **mulcurs; char buf[RECBUFSIZ], *vbuf, *kbuf; int i, j, omode, len, vsiz, ksiz, fsiz, lnum, nnum, rnum; CBLIST *alist, *dlist; const char *ap, *dp; printfflush("\n name=%s cmode=%d\n\n", name, cmode); printfflush("Creating a database with VL_CMPLEX ... "); omode = VL_OWRITER | VL_OCREAT | VL_OTRUNC | cmode; if(!(villa = vlopen(name, omode, VL_CMPLEX))){ pdperror(name); return 1; } printfflush("ok\n"); printfflush("Setting tuning parameters with 3, 4, 16, 16 ... "); vlsettuning(villa, 3, 4, 16, 16); printfflush("ok\n"); printfflush("Adding 100 records with VL_DOVER ... "); for(i = 1; i <= 100; i++){ len = sprintf(buf, "%08d", i); if(!vlput(villa, buf, len, buf, len, VL_DOVER)){ pdperror(name); vlclose(villa); return 1; } } printfflush("ok\n"); printfflush("Checking records ... "); for(i = 1; i <= 100; i++){ len = sprintf(buf, "%08d", i); if(!(vbuf = vlget(villa, buf, len, &vsiz))){ pdperror(name); vlclose(villa); return 1; } free(vbuf); if(vsiz != 8 || vlvsiz(villa, buf, len) != 8){ fprintf(stderr, "%s: %s: invalid vsiz\n", progname, name); vlclose(villa); return 1; } if(vlvnum(villa, buf, len) != 1){ fprintf(stderr, "%s: %s: invalid vnum\n", progname, name); vlclose(villa); return 1; } } printfflush("ok\n"); printfflush("Deleting x1 - x5 records ... "); for(i = 1; i <= 100; i++){ if(i % 10 < 1 || i % 10 > 5) continue; len = sprintf(buf, "%08d", i); if(!vlout(villa, buf, len)){ pdperror(name); vlclose(villa); return 1; } } printfflush("ok\n"); printfflush("Adding 100 records with VL_DOVER ... "); for(i = 1; i <= 100; i++){ len = sprintf(buf, "%08d", i); if(!vlput(villa, buf, len, buf, len, VL_DOVER)){ pdperror(name); vlclose(villa); return 1; } } printfflush("ok\n"); printfflush("Deleting x1 - x5 records ... "); for(i = 1; i <= 100; i++){ if(i % 10 < 1 || i % 10 > 5) continue; len = sprintf(buf, "%08d", i); if(!vlout(villa, buf, len)){ pdperror(name); vlclose(villa); return 1; } } printfflush("ok\n"); printfflush("Checking number of records ... "); if(vlrnum(villa) != 50){ fprintf(stderr, "%s: %s: invalid rnum\n", progname, name); vlclose(villa); return 1; } printfflush("ok\n"); printfflush("Adding 100 records with VL_DDUP ... "); for(i = 1; i <= 100; i++){ len = sprintf(buf, "%08d", i); if(!vlput(villa, buf, len, buf, len, VL_DDUP)){ pdperror(name); vlclose(villa); return 1; } } printfflush("ok\n"); printfflush("Deleting x6 - x0 records ... "); for(i = 1; i <= 100; i++){ if(i % 10 >= 1 && i % 10 <= 5) continue; len = sprintf(buf, "%08d", i); if(!vlout(villa, buf, len)){ pdperror(name); vlclose(villa); return 1; } } printfflush("ok\n"); printfflush("Optimizing the database ... "); if(!vloptimize(villa)){ pdperror(name); vlclose(villa); return 1; } printfflush("ok\n"); printfflush("Checking number of records ... "); if(vlrnum(villa) != 100){ fprintf(stderr, "%s: %s: invalid rnum\n", progname, name); vlclose(villa); return 1; } printfflush("ok\n"); printfflush("Checking records ... "); for(i = 1; i <= 100; i++){ len = sprintf(buf, "%08d", i); if(!(vbuf = vlget(villa, buf, len, &vsiz))){ pdperror(name); vlclose(villa); return 1; } free(vbuf); if(vsiz != 8){ fprintf(stderr, "%s: %s: invalid vsiz\n", progname, name); vlclose(villa); return 1; } if(vlvnum(villa, buf, len) != 1){ fprintf(stderr, "%s: %s: invalid vnum\n", progname, name); vlclose(villa); return 1; } } printfflush("ok\n"); printfflush("Deleting x6 - x0 records ... "); for(i = 1; i <= 100; i++){ if(i % 10 >= 1 && i % 10 <= 5) continue; len = sprintf(buf, "%08d", i); if(!vlout(villa, buf, len)){ pdperror(name); vlclose(villa); return 1; } } printfflush("ok\n"); printfflush("Scanning with the cursor in ascending order ... "); if(!vlcurfirst(villa)){ pdperror(name); vlclose(villa); return 1; } i = 0; do { kbuf = NULL; vbuf = NULL; if(!(kbuf = vlcurkey(villa, &ksiz)) || !(vbuf = vlcurval(villa, &vsiz))){ pdperror(name); free(kbuf); free(vbuf); vlclose(villa); return 1; } free(kbuf); free(vbuf); i++; } while(vlcurnext(villa)); if(i != 50){ fprintf(stderr, "%s: %s: invalid cursor\n", progname, name); vlclose(villa); return 1; } if(dpecode != DP_ENOITEM){ pdperror(name); vlclose(villa); return 1; } printfflush("ok\n"); printfflush("Scanning with the cursor in decending order ... "); if(!vlcurlast(villa)){ pdperror(name); vlclose(villa); return 1; } i = 0; do { kbuf = NULL; vbuf = NULL; if(!(kbuf = vlcurkey(villa, &ksiz)) || !(vbuf = vlcurval(villa, &vsiz))){ pdperror(name); free(kbuf); free(vbuf); vlclose(villa); return 1; } free(kbuf); free(vbuf); i++; } while(vlcurprev(villa)); if(i != 50){ fprintf(stderr, "%s: %s: invalid cursor\n", progname, name); vlclose(villa); return 1; } if(dpecode != DP_ENOITEM){ pdperror(name); vlclose(villa); return 1; } printfflush("ok\n"); printfflush("Adding 50 random records with VL_DDUPR ... "); for(i = 0; i < 50; i++){ len = sprintf(buf, "%08d", myrand() % 100 + 1); if(!vlput(villa, buf, len, buf, len, VL_DDUPR)){ pdperror(name); vlclose(villa); return 1; } } printfflush("ok\n"); printfflush("Deleting 80 random records ... "); i = 0; while(i < 80){ len = sprintf(buf, "%08d", myrand() % 100 + 1); if(!vlout(villa, buf, len)){ if(dpecode == DP_ENOITEM) continue; pdperror(name); vlclose(villa); return 1; } i++; } printfflush("ok\n"); alist = cblistopen(); dlist = cblistopen(); printfflush("Scanning with the cursor in ascending order ... "); if(!vlcurfirst(villa)){ pdperror(name); vlclose(villa); return 1; } i = 0; do { kbuf = NULL; vbuf = NULL; if(!(kbuf = vlcurkey(villa, &ksiz)) || !(vbuf = vlcurval(villa, &vsiz))){ pdperror(name); cblistclose(alist); cblistclose(dlist); free(kbuf); free(vbuf); vlclose(villa); return 1; } cblistpush(alist, kbuf, ksiz); free(kbuf); free(vbuf); i++; } while(vlcurnext(villa)); if(i != 20){ fprintf(stderr, "%s: %s: invalid cursor\n", progname, name); cblistclose(alist); cblistclose(dlist); vlclose(villa); return 1; } if(dpecode != DP_ENOITEM){ pdperror(name); cblistclose(alist); cblistclose(dlist); vlclose(villa); return 1; } printfflush("ok\n"); printfflush("Scanning with the cursor in decending order ... "); if(!vlcurlast(villa)){ pdperror(name); cblistclose(alist); cblistclose(dlist); vlclose(villa); return 1; } i = 0; do { kbuf = NULL; vbuf = NULL; if(!(kbuf = vlcurkey(villa, &ksiz)) || !(vbuf = vlcurval(villa, &vsiz))){ pdperror(name); free(kbuf); free(vbuf); cblistclose(alist); cblistclose(dlist); vlclose(villa); return 1; } cblistunshift(dlist, kbuf, ksiz); free(kbuf); free(vbuf); i++; } while(vlcurprev(villa)); if(i != 20){ fprintf(stderr, "%s: %s: invalid cursor\n", progname, name); cblistclose(alist); cblistclose(dlist); vlclose(villa); return 1; } if(dpecode != DP_ENOITEM){ pdperror(name); cblistclose(alist); cblistclose(dlist); vlclose(villa); return 1; } printfflush("ok\n"); printfflush("Matching result of ascending scan and desending scan ... "); for(i = 0; i < cblistnum(alist); i++){ ap = cblistval(alist, i, NULL); dp = cblistval(dlist, i, NULL); if(strcmp(ap, dp)){ fprintf(stderr, "%s: %s: not match\n", progname, name); cblistclose(alist); cblistclose(dlist); vlclose(villa); return 1; } } cblistsort(alist); for(i = 0; i < cblistnum(alist); i++){ ap = cblistval(alist, i, NULL); dp = cblistval(dlist, i, NULL); if(strcmp(ap, dp)){ fprintf(stderr, "%s: %s: not match\n", progname, name); cblistclose(alist); cblistclose(dlist); vlclose(villa); return 1; } } printfflush("ok\n"); cblistclose(alist); cblistclose(dlist); printfflush("Resetting tuning parameters with 41, 80, 32, 32 ... "); vlsettuning(villa, 41, 80, 32, 32); printfflush("ok\n"); printfflush("Adding 1000 random records with VL_DDUP ... "); for(i = 0; i < 1000; i++){ len = sprintf(buf, "%08d", myrand() % 1000 + 1); if(!vlput(villa, buf, len, buf, len, VL_DDUP)){ pdperror(name); vlclose(villa); return 1; } } printfflush("ok\n"); printfflush("Resetting tuning parameters with 8, 5, 16, 16 ... "); vlsettuning(villa, 8, 5, 16, 16); printfflush("ok\n"); printfflush("Adding 1000 random records with VL_DDUP ... "); for(i = 0; i < 1000; i++){ len = sprintf(buf, "%08d", myrand() % 1000 + 1); if(!vlput(villa, buf, len, buf, len, VL_DDUP)){ pdperror(name); vlclose(villa); return 1; } } printfflush("ok\n"); printfflush("Beginning the transaction ... "); if(!vltranbegin(villa)){ pdperror(name); vlclose(villa); return 1; } printfflush("ok\n"); printfflush("Adding 100 random records with VL_DDUP ... "); for(i = 0; i < 100; i++){ len = sprintf(buf, "%08d", myrand() % 1000 + 1); if(!vlput(villa, buf, len, buf, len, VL_DDUP)){ pdperror(name); vlclose(villa); return 1; } } printfflush("ok\n"); printfflush("Scanning and checking ... "); i = 0; for(vlcurlast(villa); (kbuf = vlcurkey(villa, &ksiz)) != NULL; vlcurprev(villa)){ if(vlvnum(villa, kbuf, ksiz) < 1 || !(vbuf = vlcurval(villa, NULL))){ pdperror(name); free(kbuf); vlclose(villa); return 1; } free(vbuf); free(kbuf); i++; } if(i != vlrnum(villa)){ fprintf(stderr, "%s: %s: invalid\n", progname, name); vlclose(villa); return 1; } printfflush("ok\n"); printfflush("Committing the transaction ... "); if(!vltrancommit(villa)){ pdperror(name); vlclose(villa); return 1; } printfflush("ok\n"); printfflush("Scanning and checking ... "); i = 0; for(vlcurlast(villa); (kbuf = vlcurkey(villa, &ksiz)) != NULL; vlcurprev(villa)){ if(vlvnum(villa, kbuf, ksiz) < 1 || !(vbuf = vlcurval(villa, NULL))){ pdperror(name); free(kbuf); vlclose(villa); return 1; } free(vbuf); free(kbuf); i++; } if(i != vlrnum(villa)){ fprintf(stderr, "%s: %s: invalid\n", progname, name); vlclose(villa); return 1; } printfflush("ok\n"); lnum = vllnum(villa); nnum = vlnnum(villa); rnum = vlrnum(villa); fsiz = vlfsiz(villa); printfflush("Beginning the transaction ... "); if(!vltranbegin(villa)){ pdperror(name); vlclose(villa); return 1; } printfflush("ok\n"); printfflush("Adding 100 random records with VL_DDUP ... "); for(i = 0; i < 100; i++){ len = sprintf(buf, "%08d", myrand() % 1000 + 1); if(!vlput(villa, buf, len, buf, len, VL_DDUP)){ pdperror(name); vlclose(villa); return 1; } } printfflush("ok\n"); printfflush("Aborting the transaction ... "); if(!vltranabort(villa)){ pdperror(name); vlclose(villa); return 1; } printfflush("ok\n"); printfflush("Checking rollback ... "); if(vlfsiz(villa) != fsiz || vllnum(villa) != lnum || vlnnum(villa) != nnum || vlrnum(villa) != rnum){ fprintf(stderr, "%s: %s: invalid\n", progname, name); vlclose(villa); return 1; } printfflush("ok\n"); printfflush("Scanning and checking ... "); i = 0; for(vlcurlast(villa); (kbuf = vlcurkey(villa, &ksiz)) != NULL; vlcurprev(villa)){ if(vlvnum(villa, kbuf, ksiz) < 1 || !(vbuf = vlcurval(villa, NULL))){ pdperror(name); free(kbuf); vlclose(villa); return 1; } free(vbuf); free(kbuf); i++; } if(i != vlrnum(villa)){ fprintf(stderr, "%s: %s: invalid\n", progname, name); vlclose(villa); return 1; } printfflush("ok\n"); printfflush("Closing the database ... "); if(!vlclose(villa)){ pdperror(name); return 1; } printfflush("ok\n"); printfflush("Creating a database with VL_CMPLEX ... "); omode = VL_OWRITER | VL_OCREAT | VL_OTRUNC | cmode; if(!(villa = vlopen(name, omode, VL_CMPLEX))){ pdperror(name); return 1; } printfflush("ok\n"); printfflush("Setting tuning parameters with 5, 6, 16, 16 ... "); vlsettuning(villa, 5, 6, 16, 16); printfflush("ok\n"); printfflush("Adding 3 * 3 records with VL_DDUP ... "); for(i = 0; i < 3; i++){ for(j = 0; j < 3; j++){ len = sprintf(buf, "%08d", j); if(!vlput(villa, buf, len, buf, -1, VL_DDUP)){ pdperror(name); vlclose(villa); return 1; } } } printfflush("ok\n"); printfflush("Inserting records with the cursor ... "); if(!vlcurjump(villa, "00000001", -1, VL_JFORWARD) || !vlcurput(villa, "first", -1, VL_CPAFTER) || !vlcurput(villa, "second", -1, VL_CPAFTER) || !vlcurnext(villa) || !vlcurput(villa, "third", -1, VL_CPAFTER) || strcmp(vlcurvalcache(villa, NULL), "third") || !vlcurput(villa, "fourth", -1, VL_CPCURRENT) || strcmp(vlcurvalcache(villa, NULL), "fourth") || !vlcurjump(villa, "00000001", -1, VL_JFORWARD) || strcmp(vlcurvalcache(villa, NULL), "00000001") || !vlcurput(villa, "one", -1, VL_CPBEFORE) || !vlcurput(villa, "two", -1, VL_CPBEFORE) || !vlcurput(villa, "three", -1, VL_CPBEFORE) || !vlcurput(villa, "five", -1, VL_CPBEFORE) || !vlcurnext(villa) || !vlcurput(villa, "four", -1, VL_CPBEFORE) || strcmp(vlcurvalcache(villa, NULL), "four") || !vlcurjump(villa, "00000001*", -1, VL_JBACKWARD) || strcmp(vlcurvalcache(villa, NULL), "00000001") || !vlcurput(villa, "omega", -1, VL_CPAFTER) || strcmp(vlcurkeycache(villa, NULL), "00000001") || strcmp(vlcurvalcache(villa, NULL), "omega") || !vlcurjump(villa, "00000000*", -1, VL_JFORWARD) || !vlcurput(villa, "alpha", -1, VL_CPBEFORE) || strcmp(vlcurvalcache(villa, NULL), "alpha") || !vlcurprev(villa) || strcmp(vlcurkeycache(villa, NULL), "00000000") || strcmp(vlcurvalcache(villa, NULL), "00000000") || !vlcurput(villa, "before", -1, VL_CPAFTER) || strcmp(vlcurvalcache(villa, NULL), "before") || !vlcurjump(villa, "00000001*", -1, VL_JFORWARD) || !vlcurput(villa, "after", -1, VL_CPBEFORE) || strcmp(vlcurvalcache(villa, NULL), "after") || !vlcurfirst(villa) || strcmp(vlcurvalcache(villa, NULL), "00000000") || !vlcurput(villa, "top", -1, VL_CPBEFORE) || strcmp(vlcurvalcache(villa, NULL), "top") || !vlcurlast(villa) || !vlcurput(villa, "bottom", -1, VL_CPAFTER) || strcmp(vlcurvalcache(villa, NULL), "bottom")){ fprintf(stderr, "%s: %s: invalid\n", progname, name); vlclose(villa); return 1; } printfflush("ok\n"); printfflush("Deleting records with the cursor ... "); if(!vlcurjump(villa, "00000000*", -1, VL_JBACKWARD) || strcmp(vlcurvalcache(villa, NULL), "before") || !vlcurout(villa) || strcmp(vlcurvalcache(villa, NULL), "alpha") || !vlcurout(villa) || strcmp(vlcurvalcache(villa, NULL), "five") || !vlcurfirst(villa) || !vlcurnext(villa) || !vlcurout(villa) || !vlcurout(villa) || !vlcurout(villa) || strcmp(vlcurvalcache(villa, NULL), "five") || !vlcurprev(villa) || strcmp(vlcurvalcache(villa, NULL), "top") || !vlcurout(villa) || strcmp(vlcurvalcache(villa, NULL), "five") || !vlcurjump(villa, "00000002", -1, VL_JBACKWARD) || strcmp(vlcurvalcache(villa, NULL), "bottom") || !vlcurout(villa) || !vlcurjump(villa, "00000001", -1, VL_JBACKWARD) || !vlcurout(villa) || !vlcurout(villa) || !vlcurout(villa) || !vlcurout(villa) || strcmp(vlcurkeycache(villa, NULL), "00000002") || strcmp(vlcurvalcache(villa, NULL), "00000002") || !vlcurout(villa) || vlcurout(villa) || !vlcurfirst(villa) || strcmp(vlcurvalcache(villa, NULL), "five")){ fprintf(stderr, "%s: %s: invalid\n", progname, name); vlclose(villa); return 1; } vlcurfirst(villa); while(vlcurout(villa)){ free(vlcurval(villa, NULL)); } if(vlrnum(villa) != 0){ printf("%d\n", vlrnum(villa)); fprintf(stderr, "%s: %s: invalid\n", progname, name); vlclose(villa); return 1; } for(i = 0; i < 1000; i++){ len = sprintf(buf, "%08d", i); if(!vlput(villa, buf, len, buf, -1, VL_DKEEP)){ pdperror(name); vlclose(villa); return 1; } } for(i = 200; i < 800; i++){ len = sprintf(buf, "%08d", i); if(!vlout(villa, buf, len)){ pdperror(name); vlclose(villa); return 1; } } vlcurfirst(villa); while(vlcurout(villa)){ free(vlcurval(villa, NULL)); } if(vlrnum(villa) != 0){ printf("%d\n", vlrnum(villa)); fprintf(stderr, "%s: %s: invalid\n", progname, name); vlclose(villa); return 1; } printfflush("ok\n"); printfflush("Adding 3 * 100 records with VL_DDUP ... "); for(i = 1; i <= 100; i++){ len = sprintf(buf, "%08d", i); for(j = 0; j < 3; j++){ if(!vlput(villa, buf, len, buf, len, VL_DDUP)){ pdperror(name); vlclose(villa); return 1; } } } printfflush("ok\n"); printfflush("Closing the database ... "); if(!vlclose(villa)){ pdperror(name); return 1; } printfflush("ok\n"); printfflush("Opening the database as a reader ... "); if(!(villa = vlopen(name, VL_OREADER, VL_CMPLEX))){ pdperror(name); return 1; } printfflush("ok\n"); printfflush("Opening multiple cursors ... "); mulcurs = cbmalloc(sizeof(VLMULCUR *) * 8); for(i = 0; i < 8; i++){ if(!(mulcurs[i] = vlmulcuropen(villa))){ pdperror(name); vlclose(villa); return 1; } } printfflush("ok\n"); printfflush("Scanning multiple cursors ... "); for(i = 0; i < 8; i++){ if(i % 2 == 0){ vlmulcurfirst(mulcurs[i]); } else { vlmulcurlast(mulcurs[i]); } } for(i = 0; i < 300; i++){ for(j = 0; j < 8; j++){ if(j % 2 == 0){ if(!(vbuf = vlmulcurkey(mulcurs[j], &vsiz))){ pdperror(name); vlclose(villa); return 1; } free(vbuf); vlmulcurnext(mulcurs[j]); } else { if(!(vbuf = vlmulcurval(mulcurs[j], &vsiz))){ pdperror(name); vlclose(villa); return 1; } free(vbuf); vlmulcurprev(mulcurs[j]); } } } printfflush("ok\n"); printfflush("Closing multiple cursors ... "); for(i = 0; i < 8; i++){ vlmulcurclose(mulcurs[i]); } free(mulcurs); printfflush("ok\n"); printfflush("Closing the database ... "); if(!vlclose(villa)){ pdperror(name); return 1; } printfflush("ok\n"); printfflush("all ok\n\n"); return 0; } /* perform wicked command */ int dowicked(const char *name, int rnum, int cb, int cmode){ VILLA *villa; CBMAP *map; int i, j, omode, len, err, ksiz, vsiz, tran, mksiz, mvsiz, rsiz; const char *mkbuf, *mvbuf; char buf[32], *kbuf, *vbuf; CBLIST *list; printfflush("\n name=%s rnum=%d\n\n", name, rnum); omode = VL_OWRITER | VL_OCREAT | VL_OTRUNC | cmode; if(!(villa = vlopen(name, omode, VL_CMPLEX))){ pdperror(name); return 1; } err = FALSE; tran = FALSE; vlsettuning(villa, 5, 10, 64, 64); map = NULL; if(cb) map = cbmapopen(); for(i = 1; i <= rnum; i++){ len = sprintf(buf, "%08d", myrand() % rnum + 1); switch(cb ? (myrand() % 5) : myrand() % 16){ case 0: putchar('O'); if(!vlput(villa, buf, len, buf, len, VL_DOVER)) err = TRUE; if(map) cbmapput(map, buf, len, buf, len, TRUE); break; case 1: putchar('K'); if(!vlput(villa, buf, len, buf, len, VL_DKEEP) && dpecode != DP_EKEEP) err = TRUE; if(map) cbmapput(map, buf, len, buf, len, FALSE); break; case 2: putchar('C'); if(!vlput(villa, buf, len, buf, len, VL_DCAT)) err = TRUE; if(map) cbmapputcat(map, buf, len, buf, len); break; case 3: putchar('D'); if(!vlout(villa, buf, len) && dpecode != DP_ENOITEM) err = TRUE; if(map) cbmapout(map, buf, len); break; case 4: putchar('G'); if((vbuf = vlget(villa, buf, len, NULL)) != NULL){ free(vbuf); } else if(dpecode != DP_ENOITEM){ err = TRUE; } break; case 5: putchar('V'); if(vlvsiz(villa, buf, len) < 0 && dpecode != DP_ENOITEM) err = TRUE; if(!vlvnum(villa, buf, len) && dpecode != DP_ENOITEM) err = TRUE; break; case 6: putchar('X'); list = cblistopen(); cblistpush(list, buf, len); cblistpush(list, buf, len); if(!vlputlist(villa, buf, len, list)) err = TRUE; cblistclose(list); break; case 7: putchar('Y'); if(!vloutlist(villa, buf, len) && dpecode != DP_ENOITEM) err = TRUE; break; case 8: putchar('Z'); if((list = vlgetlist(villa, buf, len)) != NULL){ cblistclose(list); } else if(dpecode != DP_ENOITEM){ err = TRUE; } if((vbuf = vlgetcat(villa, buf, len, NULL)) != NULL){ free(vbuf); } else if(dpecode != DP_ENOITEM){ err = TRUE; } break; case 9: putchar('Q'); if(vlcurjump(villa, buf, len, VL_JFORWARD)){ for(j = 0; j < 3 && (kbuf = vlcurkey(villa, &ksiz)); j++){ if(VL_CMPLEX(buf, len, kbuf, ksiz) > 0) err = TRUE; if(strcmp(vlcurkeycache(villa, NULL), kbuf)) err = TRUE; if((vbuf = vlcurval(villa, &vsiz)) != NULL){ if(strcmp(vlcurvalcache(villa, NULL), vbuf)) err = TRUE; free(vbuf); } else { err = TRUE; } free(kbuf); if(!vlcurnext(villa) && dpecode != DP_ENOITEM) err = TRUE; } } else { if(dpecode != DP_ENOITEM) err = TRUE; } break; case 10: putchar('W'); if(vlcurjump(villa, buf, len, VL_JBACKWARD)){ for(j = 0; j < 3 && (kbuf = vlcurkey(villa, &ksiz)); j++){ if(VL_CMPLEX(buf, len, kbuf, ksiz) < 0) err = TRUE; if(strcmp(vlcurkeycache(villa, NULL), kbuf)) err = TRUE; if((vbuf = vlcurval(villa, &vsiz)) != NULL){ if(strcmp(vlcurvalcache(villa, NULL), vbuf)) err = TRUE; free(vbuf); } else { err = TRUE; } free(kbuf); if(!vlcurprev(villa) && dpecode != DP_ENOITEM) err = TRUE; } } else { if(dpecode != DP_ENOITEM) err = TRUE; } break; case 11: putchar('L'); if(myrand() % 3 == 0 && !vlcurjump(villa, buf, len, i % 3 == 0 ? VL_JFORWARD : VL_JBACKWARD) && dpecode != DP_ENOITEM) err = TRUE; for(j = myrand() % 5; j >= 0; j--){ switch(myrand() % 6){ case 0: if(!vlcurput(villa, buf, len, VL_CPAFTER) && dpecode != DP_ENOITEM) err = TRUE; break; case 1: if(!vlcurput(villa, buf, len, VL_CPBEFORE) && dpecode != DP_ENOITEM) err = TRUE; break; case 2: if(!vlcurput(villa, buf, len, VL_CPCURRENT) && dpecode != DP_ENOITEM) err = TRUE; break; default: if(!vlcurout(villa)){ if(dpecode != DP_ENOITEM) err = TRUE; break; } break; } } break; case 12: if(tran ? myrand() % 32 != 0 : myrand() % 1024 != 0){ putchar('N'); break; } putchar('T'); if(tran){ if(myrand() % 5 == 0){ if(!vltranabort(villa)) err = TRUE; } else { if(!vltrancommit(villa)) err = TRUE; } tran = FALSE; } else { if(!vltranbegin(villa)) err = TRUE; tran = TRUE; } break; default: putchar('P'); if(!vlput(villa, buf, len, buf, len, myrand() % 3 == 0 ? VL_DDUPR : VL_DDUP)) err = TRUE; break; } if(i % 50 == 0) printfflush(" (%08d)\n", i); if(err){ pdperror(name); break; } } if(tran){ if(!vltranabort(villa)) err = TRUE; } if(!vloptimize(villa)){ pdperror(name); err = TRUE; } if((rnum = vlrnum(villa)) == -1){ pdperror(name); err = TRUE; } if(!vlcurfirst(villa)){ pdperror(name); err = TRUE; } i = 0; do { kbuf = NULL; vbuf = NULL; if(!(kbuf = vlcurkey(villa, &ksiz)) || !(vbuf = vlcurval(villa, &vsiz)) || ksiz != 8 || vsiz % 8 != 0 || vlvnum(villa, kbuf, ksiz) < 1){ pdperror(name); free(kbuf); free(vbuf); err = TRUE; break; } free(kbuf); free(vbuf); i++; } while(vlcurnext(villa)); if(i != rnum){ fprintf(stderr, "%s: %s: invalid cursor\n", progname, name); err = TRUE; } if(dpecode != DP_ENOITEM){ pdperror(name); err = TRUE; } if(!vlcurlast(villa)){ pdperror(name); err = TRUE; } i = 0; do { kbuf = NULL; vbuf = NULL; if(!(kbuf = vlcurkey(villa, &ksiz)) || !(vbuf = vlcurval(villa, &vsiz)) || ksiz != 8 || vsiz % 8 != 0 || vlvnum(villa, kbuf, ksiz) < 1){ pdperror(name); free(kbuf); free(vbuf); err = TRUE; break; } free(kbuf); free(vbuf); i++; } while(vlcurprev(villa)); if(i != rnum){ fprintf(stderr, "%s: %s: invalid cursor\n", progname, name); err = TRUE; } if(dpecode != DP_ENOITEM){ pdperror(name); err = TRUE; } if(map){ printfflush("Matching records ... "); cbmapiterinit(map); while((mkbuf = cbmapiternext(map, &mksiz)) != NULL){ mvbuf = cbmapget(map, mkbuf, mksiz, &mvsiz); if(!(vbuf = vlget(villa, mkbuf, mksiz, &rsiz))){ pdperror(name); err = TRUE; break; } if(rsiz != mvsiz || memcmp(vbuf, mvbuf, rsiz)){ fprintf(stderr, "%s: %s: unmatched record\n", progname, name); free(vbuf); err = TRUE; break; } free(vbuf); } cbmapclose(map); if(!err) printfflush("ok\n"); } if(!vlclose(villa)){ pdperror(name); return 1; } if(!err) printfflush("ok\n\n"); return err ? 1 : 0; } /* END OF FILE */ qdbm-1.8.78/hvtest.c0000644000175000017500000001531210610627747013241 0ustar mikiomikio/************************************************************************************************* * Test cases of Hovel * Copyright (C) 2000-2007 Mikio Hirabayashi * This file is part of QDBM, Quick Database Manager. * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU * Lesser General Public License as published by the Free Software Foundation; either version * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * You should have received a copy of the GNU Lesser General Public License along with QDBM; if * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. *************************************************************************************************/ #include #include #include #include #include #include #include #include #include #undef TRUE #define TRUE 1 /* boolean true */ #undef FALSE #define FALSE 0 /* boolean false */ #define DIVNUM 5 /* number of division */ #define ALIGNSIZ 16 /* basic size of alignment */ #define RECBUFSIZ 32 /* buffer for records */ /* for RISC OS */ #if defined(__riscos__) || defined(__riscos) #include int __riscosify_control = __RISCOSIFY_NO_PROCESS; #endif /* global variables */ const char *progname; /* program name */ /* function prototypes */ int main(int argc, char **argv); void usage(void); int runwrite(int argc, char **argv); int runread(int argc, char **argv); int printfflush(const char *format, ...); void pgerror(const char *name); int dowrite(char *name, int rnum, int qdbm, int sparse); int doread(char *name, int rnum, int qdbm); /* main routine */ int main(int argc, char **argv){ int rv; cbstdiobin(); progname = argv[0]; if(argc < 2) usage(); rv = 0; if(!strcmp(argv[1], "write")){ rv = runwrite(argc, argv); } else if(!strcmp(argv[1], "read")){ rv = runread(argc, argv); } else { usage(); } return rv; } /* print the usage and exit */ void usage(void){ fprintf(stderr, "%s: test cases for Hovel\n", progname); fprintf(stderr, "\n"); fprintf(stderr, "usage:\n"); fprintf(stderr, " %s write [-qdbm] [-s] name rnum\n", progname); fprintf(stderr, " %s read [-qdbm] name rnum\n", progname); fprintf(stderr, "\n"); exit(1); } /* parse arguments of write command */ int runwrite(int argc, char **argv){ char *name, *rstr; int i, sb, qdbm, rnum, rv; name = NULL; rstr = NULL; rnum = 0; sb = FALSE; qdbm = FALSE; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ if(!strcmp(argv[i], "-qdbm")){ qdbm = TRUE; } else if(!strcmp(argv[i], "-s")){ sb = TRUE; } else { usage(); } } else if(!name){ name = argv[i]; } else if(!rstr){ rstr = argv[i]; } else { usage(); } } if(!name || !rstr) usage(); rnum = atoi(rstr); if(rnum < 1) usage(); rv = dowrite(name, rnum, qdbm, sb); return rv; } /* parse arguments of read command */ int runread(int argc, char **argv){ char *name, *rstr; int i, qdbm, rnum, rv; name = NULL; rstr = NULL; rnum = 0; qdbm = FALSE; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ if(!strcmp(argv[i], "-qdbm")){ qdbm = TRUE; } else { usage(); } } else if(!name){ name = argv[i]; } else if(!rstr){ rstr = argv[i]; } else { usage(); } } if(!name || !rstr) usage(); rnum = atoi(rstr); if(rnum < 1) usage(); rv = doread(name, rnum, qdbm); return rv; } /* print formatted string and flush the buffer */ int printfflush(const char *format, ...){ va_list ap; int rv; va_start(ap, format); rv = vprintf(format, ap); if(fflush(stdout) == EOF) rv = -1; va_end(ap); return rv; } /* print an error message */ void pgerror(const char *name){ fprintf(stderr, "%s: %s: %s\n", progname, name, gdbm_strerror(gdbm_errno)); } /* perform write command */ int dowrite(char *name, int rnum, int qdbm, int sparse){ GDBM_FILE dbf; datum key, content; int i, rwmode, err, len; char buf[RECBUFSIZ]; printfflush("\n name=%s rnum=%d qdbm=%d\n\n", name, rnum, qdbm); /* open a database */ rwmode = GDBM_NEWDB | (sparse ? GDBM_SPARSE : 0); if(qdbm){ if(!(dbf = gdbm_open2(name, rwmode, 00644, rnum / DIVNUM, DIVNUM, ALIGNSIZ))){ pgerror(name); return 1; } } else { if(!(dbf = gdbm_open(name, 0, rwmode, 00644, NULL))){ pgerror(name); return 1; } } err = FALSE; /* loop for each record */ for(i = 1; i <= rnum; i++){ len = sprintf(buf, "%08d", i); key.dptr = buf; key.dsize = len; content.dptr = buf; content.dsize = len; /* store a record */ if(gdbm_store(dbf, key, content, GDBM_REPLACE) != 0){ pgerror(name); err = TRUE; break; } /* print progression */ if(rnum > 250 && i % (rnum / 250) == 0){ putchar('.'); fflush(stdout); if(i == rnum || i % (rnum / 10) == 0){ printfflush(" (%08d)\n", i); } } } /* close the database */ gdbm_close(dbf); if(!err) printfflush("ok\n\n"); return err ? 1 : 0; } /* perform read command */ int doread(char *name, int rnum, int qdbm){ GDBM_FILE dbf; datum key, content; int i, err, len; char buf[RECBUFSIZ]; printfflush("\n name=%s rnum=%d qdbm=%d\n\n", name, rnum, qdbm); /* open a database */ if(qdbm){ if(!(dbf = gdbm_open2(name, GDBM_READER, 00644, -1, -1, -1))){ pgerror(name); return 1; } } else { if(!(dbf = gdbm_open(name, 0, GDBM_READER, 00644, NULL))){ pgerror(name); return 1; } } err = FALSE; /* loop for each record */ for(i = 1; i <= rnum; i++){ /* retrieve a record */ len = sprintf(buf, "%08d", i); key.dptr = buf; key.dsize = len; content = gdbm_fetch(dbf, key); if(!content.dptr){ pgerror(name); err = TRUE; break; } free(content.dptr); /* print progression */ if(rnum > 250 && i % (rnum / 250) == 0){ putchar('.'); fflush(stdout); if(i == rnum || i % (rnum / 10) == 0){ printfflush(" (%08d)\n", i); } } } /* close the database */ gdbm_close(dbf); if(!err) printfflush("ok\n\n"); return err ? 1 : 0; } /* END OF FILE */ qdbm-1.8.78/vltsv.c0000644000175000017500000001414310610627747013103 0ustar mikiomikio/************************************************************************************************* * Mutual converter between a database of Villa and a TSV text * Copyright (C) 2000-2007 Mikio Hirabayashi * This file is part of QDBM, Quick Database Manager. * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU * Lesser General Public License as published by the Free Software Foundation; either version * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * You should have received a copy of the GNU Lesser General Public License along with QDBM; if * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. *************************************************************************************************/ #include #include #include #include #include #include #undef TRUE #define TRUE 1 /* boolean true */ #undef FALSE #define FALSE 0 /* boolean false */ /* for RISC OS */ #if defined(__riscos__) || defined(__riscos) #include int __riscosify_control = __RISCOSIFY_NO_PROCESS; #endif /* global variables */ const char *progname; /* program name */ /* function prototypes */ int main(int argc, char **argv); void usage(void); int runimport(int argc, char **argv); int runexport(int argc, char **argv); void pdperror(const char *name); char *getl(void); int doimport(const char *name, int bin); int doexport(const char *name, int bin); /* main routine */ int main(int argc, char **argv){ int rv; cbstdiobin(); progname = argv[0]; if(argc < 2) usage(); rv = 0; if(!strcmp(argv[1], "import")){ rv = runimport(argc, argv); } else if(!strcmp(argv[1], "export")){ rv = runexport(argc, argv); } else { usage(); } return rv; } /* print the usage and exit */ void usage(void){ fprintf(stderr, "%s: mutual converter between TSV and Villa database\n", progname); fprintf(stderr, "\n"); fprintf(stderr, "usage:\n"); fprintf(stderr, " %s import [-bin] name\n", progname); fprintf(stderr, " %s export [-bin] name\n", progname); fprintf(stderr, "\n"); exit(1); } /* parse arguments of import command */ int runimport(int argc, char **argv){ char *name; int i, bin, rv; name = NULL; bin = FALSE; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ if(!strcmp(argv[i], "-bin")){ bin = TRUE; } else { usage(); } } else if(!name){ name = argv[i]; } else { usage(); } } if(!name) usage(); rv = doimport(name, bin); return rv; } /* parse arguments of export command */ int runexport(int argc, char **argv){ char *name; int i, bin, rv; name = NULL; bin = FALSE; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ if(!strcmp(argv[i], "-bin")){ bin = TRUE; } else { usage(); } } else if(!name){ name = argv[i]; } else { usage(); } } if(!name) usage(); rv = doexport(name, bin); return rv; } /* print an error message */ void pdperror(const char *name){ fprintf(stderr, "%s: %s: %s\n", progname, name, dperrmsg(dpecode)); } /* read a line */ char *getl(void){ char *buf; int c, len, blen; buf = NULL; len = 0; blen = 256; while((c = getchar()) != EOF){ if(blen <= len) blen *= 2; buf = cbrealloc(buf, blen + 1); if(c == '\n') c = '\0'; buf[len++] = c; if(c == '\0') break; } if(!buf) return NULL; buf[len] = '\0'; return buf; } /* perform import command */ int doimport(const char *name, int bin){ VILLA *villa; char *buf, *kbuf, *vbuf, *ktmp, *vtmp; int i, err, ktsiz, vtsiz; /* open a database */ if(!(villa = vlopen(name, VL_OWRITER | VL_OCREAT, VL_CMPLEX))){ pdperror(name); return 1; } /* loop for each line */ err = FALSE; for(i = 1; (buf = getl()) != NULL; i++){ kbuf = buf; if((vbuf = strchr(buf, '\t')) != NULL){ *vbuf = '\0'; vbuf++; /* store a record */ if(bin){ ktmp = cbbasedecode(kbuf, &ktsiz); vtmp = cbbasedecode(vbuf, &vtsiz); if(!vlput(villa, ktmp, ktsiz, vtmp, vtsiz, VL_DDUP)){ pdperror(name); err = TRUE; } free(vtmp); free(ktmp); } else { if(!vlput(villa, kbuf, -1, vbuf, -1, VL_DDUP)){ pdperror(name); err = TRUE; break; } } } else { fprintf(stderr, "%s: %s: invalid format in line %d\n", progname, name, i); } free(buf); if(err) break; } /* close the database */ if(!vlclose(villa)){ pdperror(name); return 1; } return err ? 1 : 0; } /* perform export command */ int doexport(const char *name, int bin){ VILLA *villa; char *kbuf, *vbuf, *tmp; int err, ksiz, vsiz; /* open a database */ if(!(villa = vlopen(name, VL_OREADER, VL_CMPLEX))){ pdperror(name); return 1; } /* initialize the cursor */ vlcurfirst(villa); /* loop for each key */ err = FALSE; while((kbuf = vlcurkey(villa, &ksiz)) != NULL){ /* retrieve a value with a key */ if(!(vbuf = vlcurval(villa, &vsiz))){ pdperror(name); free(kbuf); err = TRUE; break; } /* output data */ if(bin){ tmp = cbbaseencode(kbuf, ksiz); printf("%s\t", tmp); free(tmp); tmp = cbbaseencode(vbuf, vsiz); printf("%s\n", tmp); free(tmp); } else { printf("%s\t%s\n", kbuf, vbuf); } /* free resources */ free(vbuf); free(kbuf); /* step the cursor */ vlcurnext(villa); } /* check whether all records were retrieved */ if(dpecode != DP_ENOITEM){ pdperror(name); err = TRUE; } /* close the database */ if(!vlclose(villa)){ pdperror(name); return 1; } return 0; } /* END OF FILE */ qdbm-1.8.78/Makefile.in0000644000175000017500000004372111426317772013632 0ustar mikiomikio# Makefile for QDBM #================================================================ # Setting variables #================================================================ # Generic settings SHELL = @SHELL@ srcdir = @srcdir@ VPATH = @srcdir@ SUBDIRS = plus java perl ruby cgi lab bros # Packaging PACKAGE = @PACKAGE_NAME@ VERSION = @PACKAGE_VERSION@ PACKAGEDIR = $(PACKAGE)-$(VERSION) PACKAGETGZ = $(PACKAGE)-$(VERSION).tar.gz LIBVER = @LIBVER@ LIBREV = @LIBREV@ # Targets MYHEADS = depot.h curia.h relic.h hovel.h cabin.h villa.h vista.h odeum.h MYLIBOBJS = depot.o curia.o relic.o hovel.o cabin.o villa.o vista.o odeum.o myconf.o MYLIBS = libqdbm.a libqdbm.so.$(LIBVER).$(LIBREV).0 libqdbm.so.$(LIBVER) libqdbm.so MYBINS = dpmgr dptest dptsv crmgr crtest crtsv rlmgr rltest hvmgr hvtest \ cbtest cbcodec vlmgr vltest vltsv odmgr odtest odidx qmttest MYMAN1S = dpmgr.1 dptest.1 dptsv.1 crmgr.1 crtest.1 crtsv.1 rlmgr.1 rltest.1 hvmgr.1 hvtest.1 \ cbtest.1 cbcodec.1 vlmgr.1 vltest.1 vltsv.1 odmgr.1 odtest.1 odidx.1 qmttest.1 MYMAN3S = qdbm.3 depot.3 dpopen.3 curia.3 cropen.3 relic.3 hovel.3 \ cabin.3 villa.3 vlopen.3 vista.3 odeum.3 odopen.3 MYDOCS = COPYING ChangeLog NEWS THANKS MYPCS = qdbm.pc MYWINLIBS = libqdbm.a libqdbm.dll.a MYMACLIBS = libqdbm.a libqdbm.$(LIBVER).$(LIBREV).0.dylib libqdbm.$(LIBVER).dylib libqdbm.dylib MYHPUXLIBS = libqdbm.a libqdbm.sl # Install destinations prefix = @prefix@ exec_prefix = @exec_prefix@ MYHEADDIR = @includedir@ MYLIBDIR = @libdir@ MYBINDIR = @bindir@ MYMAN1DIR = @mandir@/man1 MYMAN3DIR = @mandir@/man3 MYDATADIR = @datadir@/$(PACKAGE) MYPCDIR = @libdir@/pkgconfig DESTDIR = # Building binaries CC = @CC@ CPPFLAGS = @CPPFLAGS@ -I$(srcdir) -I$(MYHEADDIR) \ -I$(HOME)/include -I/usr/local/include @MYDEFS@ \ -D_XOPEN_SOURCE_EXTENDED=1 -D_GNU_SOURCE=1 -D__EXTENSIONS__=1 -D_HPUX_SOURCE=1 \ -D_POSIX_MAPPED_FILES=1 -D_POSIX_SYNCHRONIZED_IO=1 \ -DPIC=1 -D_THREAD_SAFE=1 -D_REENTRANT=1 -DNDEBUG CFLAGS = -Wall -pedantic -fPIC -fsigned-char -O3 -fomit-frame-pointer -fforce-addr @MYOPTS@ LD = @LD@ LIBS = -lqdbm @LIBS@ LIBLDFLAGS = @LDFLAGS@ -L. -L$(MYLIBDIR) -L$(HOME)/lib -L/usr/local/lib @LIBS@ LDFLAGS = @LDFLAGS@ -L. -L$(MYLIBDIR) -L$(HOME)/lib -L/usr/local/lib $(LIBS) LDENV = LD_RUN_PATH=/lib:/usr/lib:$(MYLIBDIR):$(HOME)/lib:/usr/local/lib AR = @AR@ ARFLAGS = rcsv RUNENV = LD_LIBRARY_PATH=.:/lib:/usr/lib:$(MYLIBDIR):$(HOME)/lib:/usr/local/lib #================================================================ # Suffix rules #================================================================ .SUFFIXES : .SUFFIXES : .c .o .c.o : $(CC) -c $(CPPFLAGS) $(CFLAGS) $< #================================================================ # Actions #================================================================ targets : @TARGETS@ all : $(MYLIBS) $(MYBINS) @printf '\n' @printf '#================================================================\n' @printf '# Ready to install.\n' @printf '#================================================================\n' static : make MYLIBS="$(MYLIBS)" LDFLAGS="-static $(LDFLAGS)" all debug : make MYLIBS="$(MYLIBS)" CPPFLAGS="$(CPPFLAGS) -UNDEBUG" \ CFLAGS="-Wall -ansi -pedantic -fPIC -fsigned-char -O2 -g" \ LDFLAGS="-static $(LDFLAGS)" all devel : make MYLIBS="$(MYLIBS)" CPPFLAGS="$(CPPFLAGS) -UNDEBUG" \ CFLAGS="-Wall -ansi -pedantic -fPIC -fsigned-char -O2 -g -pipe" all sync ; sync stable : make MYLIBS="$(MYLIBS)" CFLAGS="-Wall -ansi -pedantic -fPIC -fsigned-char -O2" all profile : make MYLIBS="$(MYLIBS)" \ CFLAGS="-Wall -pedantic -fPIC -fsigned-char -O3 -pg -g -Werror" \ LDFLAGS="-static $(LDFLAGS)" all unsigned : make MYLIBS="$(MYLIBS)" CPPFLAGS="$(CPPFLAGS) -UNDEBUG" \ CFLAGS="-Wall -ansi -pedantic -fPIC -funsigned-char -g -O2" all m64 : make MYLIBS="$(MYLIBS)" CPPFLAGS="$(CPPFLAGS) -UNDEBUG" \ CFLAGS="-Wall -ansi -pedantic -fPIC -fsigned-char -O2 -m64 -g" all pen4 : stdopt="-O3 -fomit-frame-pointer -minline-all-stringops" ; \ exopt="-march=pentium4 -minline-all-stringops -fprefetch-loop-arrays" ; \ make MYLIBS="$(MYLIBS)" \ CFLAGS="-Wall -pedantic -fPIC -fsigned-char $$stdopt $$exopt" all k8 : stdopt="-O3 -fomit-frame-pointer -minline-all-stringops" ; \ exopt="-march=k8 -minline-all-stringops -fprefetch-loop-arrays" ; \ make MYLIBS="$(MYLIBS)" \ CFLAGS="-Wall -pedantic -fPIC -fsigned-char $$stdopt $$exopt" all clean : rm -rf $(MYLIBS) $(MYBINS) *.o *.a *.so *.lo *.la a.out .libs \ *.exe *.dll.a *.dll *.dylib *.sl TAGS srcdoc gmon.out leak.log \ casket casket.* casket-* *~ version : vernum=`expr $(LIBVER)00 + $(LIBREV)` ; \ sed -e 's/_QDBM_VERSION.*/_QDBM_VERSION "$(VERSION)"/' \ -e "s/_QDBM_LIBVER.*/_QDBM_LIBVER $$vernum/" depot.h > depot.h~ [ -f depot.h~ ] && mv -f depot.h~ depot.h install : mkdir -p $(DESTDIR)$(MYHEADDIR) cd $(srcdir) && cp -Rf $(MYHEADS) $(DESTDIR)$(MYHEADDIR) mkdir -p $(DESTDIR)$(MYLIBDIR) cp -Rf $(MYLIBS) $(DESTDIR)$(MYLIBDIR) mkdir -p $(DESTDIR)$(MYBINDIR) cp -Rf $(MYBINS) $(DESTDIR)$(MYBINDIR) mkdir -p $(DESTDIR)$(MYMAN1DIR) cd $(srcdir)/man && cp -Rf $(MYMAN1S) $(DESTDIR)$(MYMAN1DIR) mkdir -p $(DESTDIR)$(MYMAN3DIR) cd $(srcdir)/man && cp -Rf $(MYMAN3S) $(DESTDIR)$(MYMAN3DIR) mkdir -p $(DESTDIR)$(MYDATADIR) cd $(srcdir) && cp -Rf $(MYDOCS) $(DESTDIR)$(MYDATADIR) mkdir -p $(DESTDIR)$(MYPCDIR) cd $(srcdir) && cp -Rf $(MYPCS) $(DESTDIR)$(MYPCDIR) @printf '\n' @printf '#================================================================\n' @printf '# Thanks for using QDBM.\n' @printf '#================================================================\n' install-strip : make DESTDIR=$(DESTDIR) install cd $(DESTDIR)$(MYBINDIR) && strip $(MYBINS) uninstall : cd $(DESTDIR)$(MYHEADDIR) && rm -f $(MYHEADS) cd $(DESTDIR)$(MYLIBDIR) && rm -f $(MYLIBS) cd $(DESTDIR)$(MYBINDIR) && rm -f $(MYBINS) cd $(DESTDIR)$(MYMAN1DIR) && rm -f $(MYMAN1S) cd $(DESTDIR)$(MYMAN3DIR) && rm -f $(MYMAN3S) rm -rf $(DESTDIR)$(MYDATADIR) cd $(DESTDIR)$(MYPCDIR) && rm -f $(MYPCS) dist : sync ; sync for dir in $(SUBDIRS) ; \ do \ if [ -d $$dir ] ; \ then \ echo Making $@ in $$dir ; \ ( cd $$dir && if [ -f configure.in ] ; then autoconf ; ./configure ; \ make dist ; fi ) ; \ fi ; \ done make version make distclean cd .. && tar cvf - $(PACKAGEDIR) | gzip -c > $(PACKAGETGZ) sync ; sync distclean : clean for dir in $(SUBDIRS) ; \ do \ if [ -d $$dir ] ; \ then \ echo Making $@ in $$dir ; \ ( cd $$dir && if [ -f Makefile ] ; then make distclean ; fi ) ; \ fi ; \ done rm -rf Makefile LTmakefile qdbm.spec qdbm.pc config.cache config.log config.status \ autom4te.cache rpm-tmp *-win32 TAGS : etags -o $@ *.c *.h sdoc : rm -rf srcdoc ./lab/ccdoc -d srcdoc -t "Source Documents of QDBM" *.h *.c check : sync ; sync rm -rf casket* $(RUNENV) $(RUNCMD) ./dptest write -s casket 500 500000 $(RUNENV) $(RUNCMD) ./dptest write casket 50000 5000 $(RUNENV) $(RUNCMD) ./dptest read casket $(RUNENV) $(RUNCMD) ./dptest read -wb casket $(RUNENV) $(RUNCMD) ./dptest rcat -c casket 50000 50 500 32 8 $(RUNENV) $(RUNCMD) ./dptest combo casket $(RUNENV) $(RUNCMD) ./dptest wicked -c casket 5000 $(RUNENV) $(RUNCMD) ./dptest wicked casket 500 $(RUNENV) $(RUNCMD) ./dpmgr repair casket $(RUNENV) $(RUNCMD) ./dpmgr optimize casket $(RUNENV) $(RUNCMD) ./dpmgr list casket rm -rf casket* $(RUNENV) $(RUNCMD) ./crtest write -s casket 500 100000 5 $(RUNENV) $(RUNCMD) ./crtest write casket 50000 500 10 $(RUNENV) $(RUNCMD) ./crtest read casket $(RUNENV) $(RUNCMD) ./crtest read -wb casket $(RUNENV) $(RUNCMD) ./crtest rcat -c casket 50000 5 10 500 32 8 $(RUNENV) $(RUNCMD) ./crtest combo casket $(RUNENV) $(RUNCMD) ./crtest wicked -c casket 5000 $(RUNENV) $(RUNCMD) ./crtest wicked casket 500 $(RUNENV) $(RUNCMD) ./crmgr repair casket $(RUNENV) $(RUNCMD) ./crmgr optimize casket $(RUNENV) $(RUNCMD) ./crmgr list casket rm -rf casket* $(RUNENV) $(RUNCMD) ./crtest write -lob casket 1000 50 10 $(RUNENV) $(RUNCMD) ./crtest read -lob casket rm -rf casket* $(RUNENV) $(RUNCMD) ./rltest write casket 5000 $(RUNENV) $(RUNCMD) ./rltest read casket 5000 $(RUNENV) $(RUNCMD) ./rlmgr list casket rm -rf casket* $(RUNENV) $(RUNCMD) ./hvtest write casket 5000 $(RUNENV) $(RUNCMD) ./hvtest read casket 5000 $(RUNENV) $(RUNCMD) ./hvmgr optimize casket $(RUNENV) $(RUNCMD) ./hvmgr list casket rm -rf casket* $(RUNENV) $(RUNCMD) ./hvtest write -qdbm -s casket 500 $(RUNENV) $(RUNCMD) ./hvtest write -qdbm casket 5000 $(RUNENV) $(RUNCMD) ./hvtest read -qdbm casket 5000 rm -rf casket* $(RUNENV) $(RUNCMD) ./cbtest sort 5000 $(RUNENV) $(RUNCMD) ./cbtest strstr 500 $(RUNENV) $(RUNCMD) ./cbtest list 50000 $(RUNENV) $(RUNCMD) ./cbtest list -d 500 $(RUNENV) $(RUNCMD) ./cbtest map 50000 500 $(RUNENV) $(RUNCMD) ./cbtest map -d 500 5 $(RUNENV) $(RUNCMD) ./cbtest heap 50000 500 $(RUNENV) $(RUNCMD) ./cbtest heap -d 500 50 $(RUNENV) $(RUNCMD) ./cbtest wicked 5000 $(RUNENV) $(RUNCMD) ./cbtest misc rm -rf casket* $(RUNENV) $(RUNCMD) ./vltest write -tune 32 31 32 32 casket 50000 $(RUNENV) $(RUNCMD) ./vltest read casket $(RUNENV) $(RUNCMD) ./vltest rdup -tune 32 31 512 256 casket 50000 50000 $(RUNENV) $(RUNCMD) ./vltest combo casket $(RUNENV) $(RUNCMD) ./vltest wicked -c casket 5000 $(RUNENV) $(RUNCMD) ./vltest wicked casket 500 $(RUNENV) $(RUNCMD) ./vlmgr repair casket $(RUNENV) $(RUNCMD) ./vlmgr optimize casket $(RUNENV) $(RUNCMD) ./vlmgr list casket rm -rf casket* $(RUNENV) $(RUNCMD) ./vltest write -int -cz -tune 32 31 32 32 casket 50000 $(RUNENV) $(RUNCMD) ./vltest read -int -vc casket $(RUNENV) $(RUNCMD) ./vltest rdup -int -cz -cc -tune 32 31 512 256 casket 50000 50000 $(RUNENV) $(RUNCMD) ./vltest combo -cz casket $(RUNENV) $(RUNCMD) ./vltest wicked -cz -c casket 5000 $(RUNENV) $(RUNCMD) ./vltest combo -cy casket $(RUNENV) $(RUNCMD) ./vltest wicked -cy -c casket 5000 $(RUNENV) $(RUNCMD) ./vltest combo -cx casket $(RUNENV) $(RUNCMD) ./vltest wicked -cx -c casket 5000 rm -rf casket* $(RUNENV) $(RUNCMD) ./odtest write casket 500 50 5000 $(RUNENV) $(RUNCMD) ./odtest read casket $(RUNENV) $(RUNCMD) ./odtest combo casket $(RUNENV) $(RUNCMD) ./odtest wicked casket 500 rm -rf casket* $(RUNENV) $(RUNCMD) ./qmttest casket 50000 10 rm -rf casket* @printf '\n' @printf '#================================================================\n' @printf '# Checking completed.\n' @printf '#================================================================\n' check-valgrind : make RUNCMD="valgrind --tool=memcheck --log-fd=1" check | tee leak.log grep ERROR leak.log grep 'at exit' leak.log world : make clean ; make cd plus ; [ -f Makefile ] || ./configure ; make clean ; make cd java ; [ -f Makefile ] || ./configure ; make clean ; make cd perl ; [ -f Makefile ] || ./configure ; make clean ; make cd ruby ; [ -f Makefile ] || ./configure ; make clean ; make cd cgi ; [ -f Makefile ] || ./configure ; make clean ; make install-world : make install cd plus ; [ -f Makefile ] || ./configure ; make install cd java ; [ -f Makefile ] || ./configure ; make install cd perl ; [ -f Makefile ] || ./configure ; make install cd ruby ; [ -f Makefile ] || ./configure ; make install cd cgi ; [ -f Makefile ] || ./configure ; make install uninstall-world : make uninstall cd plus ; [ -f Makefile ] || ./configure ; make uninstall cd java ; [ -f Makefile ] || ./configure ; make uninstall cd perl ; [ -f Makefile ] || ./configure ; make uninstall cd ruby ; [ -f Makefile ] || ./configure ; make uninstall cd cgi ; [ -f Makefile ] || ./configure ; make uninstall check-world : make check cd plus ; [ -f Makefile ] || ./configure ; make check cd java ; [ -f Makefile ] || ./configure ; make check cd perl ; [ -f Makefile ] || ./configure ; make check cd ruby ; [ -f Makefile ] || ./configure ; make check rpm : ../$(PACKAGETGZ) qdbm.spec mkdir -p rpm-tmp/{BUILD,RPMS,SOURCES,SPECS,SRPMS} mkdir -p rpm-tmp/RPMS/i386 cp ../$(PACKAGETGZ) rpm-tmp/SOURCES rpmbuild -bb --target i386 --define "_topdir `pwd`/rpm-tmp" qdbm.spec mv -f rpm-tmp/RPMS/i386/$(PACKAGE)-*$(VERSION)*.rpm .. rm -rf rpm-tmp win32pkg : test -f /bin/mgwz.dll test -f /bin/libiconv-2.dll make uninstall && make uninstall-win && make clean make mingw && strip *.exe && make install-win cd java && ./configure cd java && make uninstall && make uninstall-win && make clean cd java && make mingw cd cgi && ./configure cd cgi && make clean cd cgi && make mingw && strip *.cgi mkdir -p $(PACKAGE)-$(VERSION)-win32 cp -Rf $(MYHEADS) libqdbm.dll.a qdbm.dll *.exe *.html \ misc/README-win32.txt misc/COPYING.txt misc/win32check.bat \ /bin/mgwz.dll /bin/libiconv-2.dll \ $(PACKAGE)-$(VERSION)-win32 cp -Rf java/jqdbm.dll java/qdbm.jar java/*.html java/japidoc $(PACKAGE)-$(VERSION)-win32 mkdir -p $(PACKAGE)-$(VERSION)-win32/cgi cp -Rf cgi/*.cgi cgi/*.conf cgi/*.html $(PACKAGE)-$(VERSION)-win32/cgi zip -r $(PACKAGE)-$(VERSION)-win32.zip $(PACKAGE)-$(VERSION)-win32 mv -f $(PACKAGE)-$(VERSION)-win32.zip .. rm -rf $(PACKAGE)-$(VERSION)-win32 make uninstall && make uninstall-win && make clean cd java ; make uninstall && make uninstall-win && make clean win : make MYLIBS="$(MYWINLIBS)" CFLAGS="-Wall -ansi -pedantic -fsigned-char -O2" mingw : make CC="gcc -mno-cygwin" MYLIBS="$(MYWINLIBS)" \ CFLAGS="-Wall -fsigned-char -O2" LIBLDFLAGS="@MGWLIBS@" LDFLAGS="-L. -lqdbm @MGWLIBS@" check-win : make check install-win : make MYBINS="`for file in $(MYBINS) ; do echo $$file.exe ; done | tr '\n' ' '`" \ MYLIBS="$(MYWINLIBS)" install cp -Rf qdbm.dll $(DESTDIR)$(MYBINDIR) uninstall-win : make MYBINS="`for file in $(MYBINS) ; do echo $$file.exe ; done | tr '\n' ' '`" \ MYLIBS="$(MYWINLIBS)" uninstall rm -f $(DESTDIR)$(MYBINDIR)/qdbm.dll def : libqdbm.a ./misc/makevcdef libqdbm.a > qdbm.def mac : make MYLIBS="$(MYMACLIBS)" CFLAGS="-Wall -fsigned-char -fno-common -O2" check-mac : make RUNENV="DYLD_LIBRARY_PATH=." check install-mac : make MYLIBS="$(MYMACLIBS)" install uninstall-mac : make MYLIBS="$(MYMACLIBS)" uninstall hpux : make MYLIBS="$(MYHPUXLIBS)" check-hpux : make RUNENV="SHLIB_PATH=." check install-hpux : make MYLIBS="$(MYHPUXLIBS)" install uninstall-hpux : make MYLIBS="$(MYHPUXLIBS)" uninstall no-so : make MYLIBS="libqdbm.a" all install-no-so : make MYLIBS="libqdbm.a" install uninstall-no-so : make MYLIBS="libqdbm.a" uninstall .PHONY : all clean install check #================================================================ # Building binaries #================================================================ libqdbm.a : $(MYLIBOBJS) $(AR) $(ARFLAGS) $@ $(MYLIBOBJS) libqdbm.so.$(LIBVER).$(LIBREV).0 : $(MYLIBOBJS) if uname -a | egrep -i 'SunOS' > /dev/null ; \ then \ $(CC) -shared -Wl,-G,-h,libqdbm.so.$(LIBVER) -o $@ $(MYLIBOBJS) $(LIBLDFLAGS) ; \ else \ $(CC) -shared -Wl,-soname,libqdbm.so.$(LIBVER) -o $@ $(MYLIBOBJS) $(LIBLDFLAGS) ; \ fi libqdbm.so.$(LIBVER) : libqdbm.so.$(LIBVER).$(LIBREV).0 ln -f -s libqdbm.so.$(LIBVER).$(LIBREV).0 $@ libqdbm.so : libqdbm.so.$(LIBVER).$(LIBREV).0 ln -f -s libqdbm.so.$(LIBVER).$(LIBREV).0 $@ libqdbm.dll.a : qdbm.dll qdbm.dll : $(MYLIBOBJS) $(CC) -shared -o $@ \ -Wl,--out-implib=lib$@.a \ -Wl,--export-all-symbols \ -Wl,--enable-auto-import \ -Wl,--add-stdcall-alias \ -Wl,--whole-archive \ -Wl,--no-whole-archive $(MYLIBOBJS) $(LIBLDFLAGS) libqdbm.$(LIBVER).$(LIBREV).0.dylib : $(MYLIBOBJS) $(CC) -dynamiclib -o $@ \ -install_name $(MYLIBDIR)/libqdbm.$(LIBVER).dylib \ -current_version $(LIBVER).$(LIBREV).0 \ -compatibility_version $(LIBVER) \ $(MYLIBOBJS) $(LIBLDFLAGS) libqdbm.$(LIBVER).dylib : libqdbm.$(LIBVER).$(LIBREV).0.dylib ln -f -s libqdbm.$(LIBVER).$(LIBREV).0.dylib $@ libqdbm.dylib : libqdbm.$(LIBVER).$(LIBREV).0.dylib ln -f -s libqdbm.$(LIBVER).$(LIBREV).0.dylib $@ libqdbm.sl : $(MYLIBOBJS) $(CC) -shared -Wl,-b -o $@ $(MYLIBOBJS) $(LIBLDFLAGS) dpmgr : dpmgr.o $(MYLIBS) $(LDENV) $(CC) $(CFLAGS) -o $@ dpmgr.o $(LDFLAGS) dptest : dptest.o $(MYLIBS) $(LDENV) $(CC) $(CFLAGS) -o $@ dptest.o $(LDFLAGS) dptsv : dptsv.o $(MYLIBS) $(LDENV) $(CC) $(CFLAGS) -o $@ dptsv.o $(LDFLAGS) crmgr : crmgr.o $(MYLIBS) $(LDENV) $(CC) $(CFLAGS) -o $@ crmgr.o $(LDFLAGS) crtest : crtest.o $(MYLIBS) $(LDENV) $(CC) $(CFLAGS) -o $@ crtest.o $(LDFLAGS) crtsv : crtsv.o $(MYLIBS) $(LDENV) $(CC) $(CFLAGS) -o $@ crtsv.o $(LDFLAGS) rlmgr : rlmgr.o $(MYLIBS) $(LDENV) $(CC) $(CFLAGS) -o $@ rlmgr.o $(LDFLAGS) rltest : rltest.o $(MYLIBS) $(LDENV) $(CC) $(CFLAGS) -o $@ rltest.o $(LDFLAGS) hvmgr : hvmgr.o $(MYLIBS) $(LDENV) $(CC) $(CFLAGS) -o $@ hvmgr.o $(LDFLAGS) hvtest : hvtest.o $(MYLIBS) $(LDENV) $(CC) $(CFLAGS) -o $@ hvtest.o $(LDFLAGS) cbtest : cbtest.o $(MYLIBS) $(LDENV) $(CC) $(CFLAGS) -o $@ cbtest.o $(LDFLAGS) cbcodec : cbcodec.o $(MYLIBS) $(LDENV) $(CC) $(CFLAGS) -o $@ cbcodec.o $(LDFLAGS) vlmgr : vlmgr.o $(MYLIBS) $(LDENV) $(CC) $(CFLAGS) -o $@ vlmgr.o $(LDFLAGS) vltest : vltest.o $(MYLIBS) $(LDENV) $(CC) $(CFLAGS) -o $@ vltest.o $(LDFLAGS) vltsv : vltsv.o $(MYLIBS) $(LDENV) $(CC) $(CFLAGS) -o $@ vltsv.o $(LDFLAGS) odmgr : odmgr.o $(MYLIBS) $(LDENV) $(CC) $(CFLAGS) -o $@ odmgr.o $(LDFLAGS) odtest : odtest.o $(MYLIBS) $(LDENV) $(CC) $(CFLAGS) -o $@ odtest.o $(LDFLAGS) odidx : odidx.o $(MYLIBS) $(LDENV) $(CC) $(CFLAGS) -o $@ odidx.o $(LDFLAGS) qmttest : qmttest.o $(MYLIBS) $(LDENV) $(CC) $(CFLAGS) -o $@ qmttest.o $(LDFLAGS) depot.o : depot.h myconf.h curia.o : depot.h curia.h myconf.h relic.o : depot.h relic.h myconf.h hovel.o : depot.h curia.h hovel.h myconf.h cabin.o : cabin.h myconf.h villa.o : depot.h cabin.h villa.h myconf.h vista.o : depot.h curia.h cabin.h villa.h vista.h myconf.h villa.c odeum.o : depot.h curia.h cabin.h villa.h myconf.h myconf.o : myconf.h dpmgr.o dptest.o dptsv.o : depot.h cabin.h crmgr.o crtest.o crtsv.o : depot.h curia.h cabin.h rlmgr.o rltest.o : depot.h relic.h cabin.h hvmgr.o hvtest.o : depot.h curia.h hovel.h cabin.h cbtest.o cbcodec.o : cabin.h vlmgr.o vltest.o vltsv.o : depot.h cabin.h villa.h odmgr.o odtest.o odidx.o : depot.h curia.h cabin.h villa.h odeum.h # END OF FILE qdbm-1.8.78/curia.c0000644000175000017500000010015210705130230013001 0ustar mikiomikio/************************************************************************************************* * Implementation of Curia * Copyright (C) 2000-2007 Mikio Hirabayashi * This file is part of QDBM, Quick Database Manager. * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU * Lesser General Public License as published by the Free Software Foundation; either version * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * You should have received a copy of the GNU Lesser General Public License along with QDBM; if * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. *************************************************************************************************/ #define QDBM_INTERNAL 1 #include "curia.h" #include "myconf.h" #define CR_NAMEMAX 512 /* max size of a database name */ #define CR_DPMAX 512 /* max number of division of a database */ #define CR_DIRMODE 00755 /* permission of a creating directory */ #define CR_FILEMODE 00644 /* permission of a creating file */ #define CR_PATHBUFSIZ 1024 /* size of a path buffer */ #define CR_DEFDNUM 5 /* default number of division of a database */ #define CR_ATTRBNUM 16 /* bucket number of attrubute database */ #define CR_DPNAME "depot" /* name of each sub database */ #define CR_KEYDNUM "dnum" /* key of division number */ #define CR_KEYLRNUM "lrnum" /* key of the number of large objects */ #define CR_TMPFSUF MYEXTSTR "crtmp" /* suffix of a temporary directory */ #define CR_LOBDIR "lob" /* name of the directory of large objects */ #define CR_LOBDDEPTH 2 /* depth of the directories of large objects */ #define CR_NUMBUFSIZ 32 /* size of a buffer for a number */ #define CR_IOBUFSIZ 8192 /* size of an I/O buffer */ /* private function prototypes */ static char *crstrdup(const char *str); static int crdpgetnum(DEPOT *depot, const char *kbuf, int ksiz); static char *crgetlobpath(CURIA *curia, const char *kbuf, int ksiz); static int crmklobdir(const char *path); static int crrmlobdir(const char *path); static int crcplobdir(CURIA *curia, const char *path); static int crwrite(int fd, const void *buf, int size); static int crread(int fd, void *buf, int size); /************************************************************************************************* * public objects *************************************************************************************************/ /* Get a database handle. */ CURIA *cropen(const char *name, int omode, int bnum, int dnum){ DEPOT *attr, **depots; char path[CR_PATHBUFSIZ], *tname; int i, j, dpomode, inode, lrnum; struct stat sbuf; CURIA *curia; assert(name); if(dnum < 1) dnum = CR_DEFDNUM; if(dnum > CR_DPMAX) dnum = CR_DPMAX; if(strlen(name) > CR_NAMEMAX){ dpecodeset(DP_EMISC, __FILE__, __LINE__); return NULL; } dpomode = DP_OREADER; if(omode & CR_OWRITER){ dpomode = DP_OWRITER; if(omode & CR_OCREAT) dpomode |= DP_OCREAT; if(omode & CR_OTRUNC) dpomode |= DP_OTRUNC; if(omode & CR_OSPARSE) dpomode |= DP_OSPARSE; } if(omode & CR_ONOLCK) dpomode |= DP_ONOLCK; if(omode & CR_OLCKNB) dpomode |= DP_OLCKNB; attr = NULL; lrnum = 0; if((omode & CR_OWRITER) && (omode & CR_OCREAT)){ if(mkdir(name, CR_DIRMODE) == -1 && errno != EEXIST){ dpecodeset(DP_EMKDIR, __FILE__, __LINE__); return NULL; } sprintf(path, "%s%c%s", name, MYPATHCHR, CR_DPNAME); if(!(attr = dpopen(path, dpomode, CR_ATTRBNUM))) return NULL; if(dprnum(attr) > 0){ if((dnum = crdpgetnum(attr, CR_KEYDNUM, -1)) < 1 || (lrnum = crdpgetnum(attr, CR_KEYLRNUM, -1)) < 0){ dpclose(attr); dpecodeset(DP_EBROKEN, __FILE__, __LINE__); return NULL; } } else { if(!dpput(attr, CR_KEYDNUM, -1, (char *)&dnum, sizeof(int), DP_DOVER) || !dpput(attr, CR_KEYLRNUM, -1, (char *)&lrnum, sizeof(int), DP_DOVER)){ dpclose(attr); return NULL; } for(i = 0; i < dnum; i++){ sprintf(path, "%s%c%04d", name, MYPATHCHR, i + 1); if(mkdir(path, CR_DIRMODE) == -1 && errno != EEXIST){ dpclose(attr); dpecodeset(DP_EMKDIR, __FILE__, __LINE__); return NULL; } } } } if(!attr){ sprintf(path, "%s%c%s", name, MYPATHCHR, CR_DPNAME); if(!(attr = dpopen(path, dpomode, 1))) return NULL; if(!(omode & CR_OTRUNC)){ if((dnum = crdpgetnum(attr, CR_KEYDNUM, -1)) < 1 || (lrnum = crdpgetnum(attr, CR_KEYLRNUM, -1)) < 0){ dpclose(attr); dpecodeset(DP_EBROKEN, __FILE__, __LINE__); return NULL; } } } if(omode & CR_OTRUNC){ for(i = 0; i < CR_DPMAX; i++){ sprintf(path, "%s%c%04d%c%s", name, MYPATHCHR, i + 1, MYPATHCHR, CR_DPNAME); if(unlink(path) == -1 && errno != ENOENT){ dpclose(attr); dpecodeset(DP_EUNLINK, __FILE__, __LINE__); return NULL; } sprintf(path, "%s%c%04d%c%s", name, MYPATHCHR, i + 1, MYPATHCHR, CR_LOBDIR); if(!crrmlobdir(path)){ dpclose(attr); return NULL; } if(i >= dnum){ sprintf(path, "%s%c%04d", name, MYPATHCHR, i + 1); if(rmdir(path) == -1 && errno != ENOENT){ dpclose(attr); dpecodeset(DP_ERMDIR, __FILE__, __LINE__); return NULL; } } } errno = 0; } if(lstat(name, &sbuf) == -1){ dpclose(attr); dpecodeset(DP_ESTAT, __FILE__, __LINE__); return NULL; } inode = sbuf.st_ino; if(!(depots = malloc(dnum * sizeof(DEPOT *)))){ dpclose(attr); dpecodeset(DP_EALLOC, __FILE__, __LINE__); return NULL; } for(i = 0; i < dnum; i++){ sprintf(path, "%s%c%04d%c%s", name, MYPATHCHR, i + 1, MYPATHCHR, CR_DPNAME); if(!(depots[i] = dpopen(path, dpomode, bnum))){ for(j = 0; j < i; j++){ dpclose(depots[j]); } free(depots); dpclose(attr); return NULL; } } curia = malloc(sizeof(CURIA)); tname = crstrdup(name); if(!curia || !tname){ free(curia); free(tname); for(i = 0; i < dnum; i++){ dpclose(depots[i]); } free(depots); dpclose(attr); dpecodeset(DP_EALLOC, __FILE__, __LINE__); return NULL; } curia->name = tname; curia->wmode = (omode & CR_OWRITER); curia->inode = inode; curia->attr = attr; curia->depots = depots; curia->dnum = dnum; curia->inum = 0; curia->lrnum = lrnum; return curia; } /* Close a database handle. */ int crclose(CURIA *curia){ int i, err; assert(curia); err = FALSE; for(i = 0; i < curia->dnum; i++){ if(!dpclose(curia->depots[i])) err = TRUE; } free(curia->depots); if(curia->wmode){ if(!dpput(curia->attr, CR_KEYLRNUM, -1, (char *)&(curia->lrnum), sizeof(int), DP_DOVER)) err = TRUE; } if(!dpclose(curia->attr)) err = TRUE; free(curia->name); free(curia); return err ? FALSE : TRUE; } /* Store a record. */ int crput(CURIA *curia, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int dmode){ int dpdmode; int tnum; assert(curia && kbuf && vbuf); if(!curia->wmode){ dpecodeset(DP_EMODE, __FILE__, __LINE__); return FALSE; } if(ksiz < 0) ksiz = strlen(kbuf); switch(dmode){ case CR_DKEEP: dpdmode = DP_DKEEP; break; case CR_DCAT: dpdmode = DP_DCAT; break; default: dpdmode = DP_DOVER; break; } tnum = dpouterhash(kbuf, ksiz) % curia->dnum; return dpput(curia->depots[tnum], kbuf, ksiz, vbuf, vsiz, dpdmode); } /* Delete a record. */ int crout(CURIA *curia, const char *kbuf, int ksiz){ int tnum; assert(curia && kbuf); if(!curia->wmode){ dpecodeset(DP_EMODE, __FILE__, __LINE__); return FALSE; } if(ksiz < 0) ksiz = strlen(kbuf); tnum = dpouterhash(kbuf, ksiz) % curia->dnum; return dpout(curia->depots[tnum], kbuf, ksiz); } /* Retrieve a record. */ char *crget(CURIA *curia, const char *kbuf, int ksiz, int start, int max, int *sp){ int tnum; assert(curia && kbuf && start >= 0); if(ksiz < 0) ksiz = strlen(kbuf); tnum = dpouterhash(kbuf, ksiz) % curia->dnum; return dpget(curia->depots[tnum], kbuf, ksiz, start, max, sp); } /* Retrieve a record and write the value into a buffer. */ int crgetwb(CURIA *curia, const char *kbuf, int ksiz, int start, int max, char *vbuf){ int tnum; assert(curia && kbuf && start >= 0 && max >= 0 && vbuf); if(ksiz < 0) ksiz = strlen(kbuf); tnum = dpouterhash(kbuf, ksiz) % curia->dnum; return dpgetwb(curia->depots[tnum], kbuf, ksiz, start, max, vbuf); } /* Get the size of the value of a record. */ int crvsiz(CURIA *curia, const char *kbuf, int ksiz){ int tnum; assert(curia && kbuf); if(ksiz < 0) ksiz = strlen(kbuf); tnum = dpouterhash(kbuf, ksiz) % curia->dnum; return dpvsiz(curia->depots[tnum], kbuf, ksiz); } /* Initialize the iterator of a database handle. */ int criterinit(CURIA *curia){ int i, err; assert(curia); err = FALSE; for(i = 0; i < curia->dnum; i++){ if(!dpiterinit(curia->depots[i])){ err = TRUE; break; } } curia->inum = 0; return err ? FALSE : TRUE; } /* Get the next key of the iterator. */ char *criternext(CURIA *curia, int *sp){ char *kbuf; assert(curia); kbuf = NULL; while(curia->inum < curia->dnum && !(kbuf = dpiternext(curia->depots[curia->inum], sp))){ if(dpecode != DP_ENOITEM) return NULL; (curia->inum)++; } return kbuf; } /* Set alignment of a database handle. */ int crsetalign(CURIA *curia, int align){ int i, err; assert(curia); if(!curia->wmode){ dpecodeset(DP_EMODE, __FILE__, __LINE__); return FALSE; } err = FALSE; for(i = 0; i < curia->dnum; i++){ if(!dpsetalign(curia->depots[i], align)){ err = TRUE; break; } } return err ? FALSE : TRUE; } /* Set the size of the free block pool of a database handle. */ int crsetfbpsiz(CURIA *curia, int size){ int i, err; assert(curia && size >= 0); if(!curia->wmode){ dpecodeset(DP_EMODE, __FILE__, __LINE__); return FALSE; } err = FALSE; for(i = 0; i < curia->dnum; i++){ if(!dpsetfbpsiz(curia->depots[i], size)){ err = TRUE; break; } } return err ? FALSE : TRUE; } /* Synchronize contents of updating a database with the files and the devices. */ int crsync(CURIA *curia){ int i, err; assert(curia); if(!curia->wmode){ dpecodeset(DP_EMODE, __FILE__, __LINE__); return FALSE; } err = FALSE; if(!dpput(curia->attr, CR_KEYLRNUM, -1, (char *)&(curia->lrnum), sizeof(int), DP_DOVER) || !dpsync(curia->attr)) err = TRUE; for(i = 0; i < curia->dnum; i++){ if(!dpsync(curia->depots[i])){ err = TRUE; break; } } return err ? FALSE : TRUE; } /* Optimize a database. */ int croptimize(CURIA *curia, int bnum){ int i, err; assert(curia); if(!curia->wmode){ dpecodeset(DP_EMODE, __FILE__, __LINE__); return FALSE; } err = FALSE; for(i = 0; i < curia->dnum; i++){ if(!dpoptimize(curia->depots[i], bnum)){ err = TRUE; break; } } curia->inum = 0; return err ? FALSE : TRUE; } /* Get the name of a database. */ char *crname(CURIA *curia){ char *name; assert(curia); if(!(name = crstrdup(curia->name))){ dpecodeset(DP_EALLOC, __FILE__, __LINE__); return NULL; } return name; } /* Get the total size of database files. */ int crfsiz(CURIA *curia){ int i, sum, rv; assert(curia); if((sum = dpfsiz(curia->attr)) == -1) return -1; for(i = 0; i < curia->dnum; i++){ if((rv = dpfsiz(curia->depots[i])) == -1) return -1; sum += rv; } return sum; } /* Get the total size of database files as double-precision value. */ double crfsizd(CURIA *curia){ double sum; int i, rv; assert(curia); sum = 0.0; if((sum = dpfsiz(curia->attr)) < 0) return -1.0; for(i = 0; i < curia->dnum; i++){ if((rv = dpfsiz(curia->depots[i])) == -1) return -1.0; sum += rv; } return sum; } /* Get the total number of the elements of each bucket array. */ int crbnum(CURIA *curia){ int i, sum, rv; assert(curia); sum = 0; for(i = 0; i < curia->dnum; i++){ rv = dpbnum(curia->depots[i]); if(rv == -1) return -1; sum += rv; } return sum; } /* Get the total number of the used elements of each bucket array. */ int crbusenum(CURIA *curia){ int i, sum, rv; assert(curia); sum = 0; for(i = 0; i < curia->dnum; i++){ rv = dpbusenum(curia->depots[i]); if(rv == -1) return -1; sum += rv; } return sum; } /* Get the number of the records stored in a database. */ int crrnum(CURIA *curia){ int i, sum, rv; assert(curia); sum = 0; for(i = 0; i < curia->dnum; i++){ rv = dprnum(curia->depots[i]); if(rv == -1) return -1; sum += rv; } return sum; } /* Check whether a database handle is a writer or not. */ int crwritable(CURIA *curia){ assert(curia); return curia->wmode; } /* Check whether a database has a fatal error or not. */ int crfatalerror(CURIA *curia){ int i; assert(curia); if(dpfatalerror(curia->attr)) return TRUE; for(i = 0; i < curia->dnum; i++){ if(dpfatalerror(curia->depots[i])) return TRUE; } return FALSE; } /* Get the inode number of a database directory. */ int crinode(CURIA *curia){ assert(curia); return curia->inode; } /* Get the last modified time of a database. */ time_t crmtime(CURIA *curia){ assert(curia); return dpmtime(curia->attr); } /* Remove a database directory. */ int crremove(const char *name){ struct stat sbuf; CURIA *curia; char path[CR_PATHBUFSIZ]; assert(name); if(lstat(name, &sbuf) == -1){ dpecodeset(DP_ESTAT, __FILE__, __LINE__); return FALSE; } if((curia = cropen(name, CR_OWRITER | CR_OTRUNC, 1, 1)) != NULL) crclose(curia); sprintf(path, "%s%c0001%c%s", name, MYPATHCHR, MYPATHCHR, CR_DPNAME); dpremove(path); sprintf(path, "%s%c0001", name, MYPATHCHR); if(rmdir(path) == -1){ dpecodeset(DP_ERMDIR, __FILE__, __LINE__); return FALSE; } sprintf(path, "%s%c%s", name, MYPATHCHR, CR_DPNAME); if(!dpremove(path)) return FALSE; if(rmdir(name) == -1){ dpecodeset(DP_ERMDIR, __FILE__, __LINE__); return FALSE; } return TRUE; } /* Repair a broken database directory. */ int crrepair(const char *name){ CURIA *tcuria; DEPOT *tdepot; char path[CR_PATHBUFSIZ], *kbuf, *vbuf; struct stat sbuf; int i, j, err, flags, bnum, dnum, ksiz, vsiz; assert(name); err = FALSE; flags = 0; bnum = 0; dnum = 0; sprintf(path, "%s%c%s", name, MYPATHCHR, CR_DPNAME); if(lstat(path, &sbuf) != -1){ if((tdepot = dpopen(path, DP_OREADER, -1)) != NULL){ flags = dpgetflags(tdepot); dpclose(tdepot); } } for(i = 1; i <= CR_DPMAX; i++){ sprintf(path, "%s%c%04d%c%s", name, MYPATHCHR, i, MYPATHCHR, CR_DPNAME); if(lstat(path, &sbuf) != -1){ dnum++; if(!dprepair(path)) err = TRUE; if((tdepot = dpopen(path, DP_OREADER, -1)) != NULL){ bnum += dpbnum(tdepot); dpclose(tdepot); } } } if(dnum < CR_DEFDNUM) dnum = CR_DEFDNUM; bnum /= dnum; sprintf(path, "%s%s", name, CR_TMPFSUF); if((tcuria = cropen(path, CR_OWRITER | CR_OCREAT | CR_OTRUNC, bnum, dnum)) != NULL){ if(!crsetflags(tcuria, flags)) err = TRUE; for(i = 1; i <= CR_DPMAX; i++){ sprintf(path, "%s%c%04d%c%s", name, MYPATHCHR, i, MYPATHCHR, CR_DPNAME); if(lstat(path, &sbuf) != -1){ if((tdepot = dpopen(path, DP_OREADER, -1)) != NULL){ if(!dpiterinit(tdepot)) err = TRUE; while((kbuf = dpiternext(tdepot, &ksiz)) != NULL){ if((vbuf = dpget(tdepot, kbuf, ksiz, 0, -1, &vsiz)) != NULL){ if(!crput(tcuria, kbuf, ksiz, vbuf, vsiz, CR_DKEEP)) err = TRUE; free(vbuf); } free(kbuf); } dpclose(tdepot); } else { err = TRUE; } } for(j = 0; j <= CR_DPMAX; j++){ sprintf(path, "%s%c%04d%c%s", name, MYPATHCHR, j, MYPATHCHR, CR_LOBDIR); if(lstat(path, &sbuf) != -1){ if(!crcplobdir(tcuria, path)) err = TRUE; } } } if(!crclose(tcuria)) err = TRUE; if(!crremove(name)) err = TRUE; sprintf(path, "%s%s", name, CR_TMPFSUF); if(rename(path, name) == -1){ if(!err) dpecodeset(DP_EMISC, __FILE__, __LINE__); err = TRUE; } } else { err = TRUE; } return err ? FALSE : TRUE; } /* Dump all records as endian independent data. */ int crexportdb(CURIA *curia, const char *name){ char path[CR_PATHBUFSIZ], *kbuf, *vbuf, *pbuf; int i, err, *fds, ksiz, vsiz, psiz; assert(curia && name); if(!(criterinit(curia))) return FALSE; if(mkdir(name, CR_DIRMODE) == -1 && errno != EEXIST){ dpecodeset(DP_EMKDIR, __FILE__, __LINE__); return FALSE; } err = FALSE; fds = malloc(sizeof(int) * curia->dnum); for(i = 0; i < curia->dnum; i++){ sprintf(path, "%s%c%04d", name, MYPATHCHR, i + 1); if((fds[i] = open(path, O_RDWR | O_CREAT | O_TRUNC, CR_FILEMODE)) == -1){ if(!err) dpecodeset(DP_EOPEN, __FILE__, __LINE__); err = TRUE; break; } } while(!err && (kbuf = criternext(curia, &ksiz)) != NULL){ if((vbuf = crget(curia, kbuf, ksiz, 0, -1, &vsiz)) != NULL){ if((pbuf = malloc(ksiz + vsiz + CR_NUMBUFSIZ * 2)) != NULL){ psiz = 0; psiz += sprintf(pbuf + psiz, "%X\n%X\n", ksiz, vsiz); memcpy(pbuf + psiz, kbuf, ksiz); psiz += ksiz; pbuf[psiz++] = '\n'; memcpy(pbuf + psiz, vbuf, vsiz); psiz += vsiz; pbuf[psiz++] = '\n'; if(!crwrite(fds[curia->inum], pbuf, psiz)){ dpecodeset(DP_EWRITE, __FILE__, __LINE__); err = TRUE; } free(pbuf); } else { dpecodeset(DP_EALLOC, __FILE__, __LINE__); err = TRUE; } free(vbuf); } else { err = TRUE; } free(kbuf); } for(i = 0; i < curia->dnum; i++){ if(fds[i] != -1 && close(fds[i]) == -1){ if(!err) dpecodeset(DP_ECLOSE, __FILE__, __LINE__); err = TRUE; } } free(fds); return !err && !crfatalerror(curia); } /* Load all records from endian independent data. */ int crimportdb(CURIA *curia, const char *name){ DEPOT *depot; char ipath[CR_PATHBUFSIZ], opath[CR_PATHBUFSIZ], *kbuf, *vbuf; int i, err, ksiz, vsiz; struct stat sbuf; assert(curia && name); if(!curia->wmode){ dpecodeset(DP_EMODE, __FILE__, __LINE__); return FALSE; } if(crrnum(curia) > 0){ dpecodeset(DP_EMISC, __FILE__, __LINE__); return FALSE; } err = FALSE; for(i = 0; !err && i < CR_DPMAX; i++){ sprintf(ipath, "%s%c%04d", name, MYPATHCHR, i + 1); if(lstat(ipath, &sbuf) == -1 || !S_ISREG(sbuf.st_mode)) break; sprintf(opath, "%s%c%04d%s", curia->name, MYPATHCHR, i + 1, CR_TMPFSUF); if((depot = dpopen(opath, DP_OWRITER | DP_OCREAT | DP_OTRUNC, -1)) != NULL){ if(dpimportdb(depot, ipath)){ dpiterinit(depot); while((kbuf = dpiternext(depot, &ksiz)) != NULL){ if((vbuf = dpget(depot, kbuf, ksiz, 0, -1, &vsiz)) != NULL){ if(!crput(curia, kbuf, ksiz, vbuf, vsiz, CR_DKEEP)) err = TRUE; free(vbuf); } else { err = TRUE; } free(kbuf); } } else { err = TRUE; } if(!dpclose(depot)) err = TRUE; if(!dpremove(opath)) err = TRUE; } else { err = TRUE; } } return !err && !crfatalerror(curia); } /* Retrieve a record directly from a database directory. */ char *crsnaffle(const char *name, const char *kbuf, int ksiz, int *sp){ char path[CR_PATHBUFSIZ], *vbuf; int dnum, vsiz, tnum; assert(name && kbuf); if(ksiz < 0) ksiz = strlen(kbuf); sprintf(path, "%s%c%s", name, MYPATHCHR, CR_DPNAME); if(!(vbuf = dpsnaffle(path, CR_KEYDNUM, -1, &vsiz)) || vsiz != sizeof(int) || (dnum = *(int *)vbuf) < 1){ free(vbuf); dpecodeset(DP_EBROKEN, __FILE__, __LINE__); return NULL; } free(vbuf); tnum = dpouterhash(kbuf, ksiz) % dnum; sprintf(path, "%s%c%04d%c%s", name, MYPATHCHR, tnum + 1, MYPATHCHR, CR_DPNAME); return dpsnaffle(path, kbuf, ksiz, sp); } /* Store a large object. */ int crputlob(CURIA *curia, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int dmode){ char *path; int mode, fd, err, be; struct stat sbuf; assert(curia && kbuf && vbuf); if(!curia->wmode){ dpecodeset(DP_EMODE, __FILE__, __LINE__); return FALSE; } if(ksiz < 0) ksiz = strlen(kbuf); if(vsiz < 0) vsiz = strlen(vbuf); if(!(path = crgetlobpath(curia, kbuf, ksiz))) return FALSE; if(!crmklobdir(path)){ free(path); return FALSE; } be = lstat(path, &sbuf) != -1 && S_ISREG(sbuf.st_mode); mode = O_RDWR | O_CREAT; if(dmode & CR_DKEEP) mode |= O_EXCL; if(dmode & CR_DCAT){ mode |= O_APPEND; } else { mode |= O_TRUNC; } if((fd = open(path, mode, CR_FILEMODE)) == -1){ free(path); dpecodeset(DP_EOPEN, __FILE__, __LINE__); if(dmode == CR_DKEEP) dpecodeset(DP_EKEEP, __FILE__, __LINE__); return FALSE; } free(path); err = FALSE; if(crwrite(fd, vbuf, vsiz) == -1){ err = TRUE; dpecodeset(DP_EWRITE, __FILE__, __LINE__); } if(close(fd) == -1){ err = TRUE; dpecodeset(DP_ECLOSE, __FILE__, __LINE__); } if(!err && !be) (curia->lrnum)++; return err ? FALSE : TRUE; } /* Delete a large object. */ int croutlob(CURIA *curia, const char *kbuf, int ksiz){ char *path; int err, be; struct stat sbuf; assert(curia && kbuf); if(!curia->wmode){ dpecodeset(DP_EMODE, __FILE__, __LINE__); return FALSE; } if(ksiz < 0) ksiz = strlen(kbuf); if(!(path = crgetlobpath(curia, kbuf, ksiz))) return FALSE; be = lstat(path, &sbuf) != -1 && S_ISREG(sbuf.st_mode); err = FALSE; if(unlink(path) == -1){ err = TRUE; dpecodeset(DP_ENOITEM, __FILE__, __LINE__); } free(path); if(!err && be) (curia->lrnum)--; return err ? FALSE : TRUE; } /* Retrieve a large object. */ char *crgetlob(CURIA *curia, const char *kbuf, int ksiz, int start, int max, int *sp){ char *path, *buf; struct stat sbuf; int fd, size; assert(curia && kbuf && start >= 0); if(ksiz < 0) ksiz = strlen(kbuf); if(!(path = crgetlobpath(curia, kbuf, ksiz))) return NULL; if((fd = open(path, O_RDONLY, CR_FILEMODE)) == -1){ free(path); dpecodeset(DP_ENOITEM, __FILE__, __LINE__); return NULL; } free(path); if(fstat(fd, &sbuf) == -1){ close(fd); dpecodeset(DP_ESTAT, __FILE__, __LINE__); return NULL; } if(start > sbuf.st_size){ close(fd); dpecodeset(DP_ENOITEM, __FILE__, __LINE__); return NULL; } if(lseek(fd, start, SEEK_SET) == -1){ close(fd); dpecodeset(DP_ESEEK, __FILE__, __LINE__); return NULL; } if(max < 0) max = sbuf.st_size; if(!(buf = malloc(max + 1))){ close(fd); dpecodeset(DP_EALLOC, __FILE__, __LINE__); return NULL; } size = crread(fd, buf, max); close(fd); if(size == -1){ free(buf); dpecodeset(DP_EREAD, __FILE__, __LINE__); return NULL; } buf[size] = '\0'; if(sp) *sp = size; return buf; } /* Get the file descriptor of a large object. */ int crgetlobfd(CURIA *curia, const char *kbuf, int ksiz){ char *path; int fd; assert(curia && kbuf); if(ksiz < 0) ksiz = strlen(kbuf); if(!(path = crgetlobpath(curia, kbuf, ksiz))) return -1; if((fd = open(path, curia->wmode ? O_RDWR: O_RDONLY, CR_FILEMODE)) == -1){ free(path); dpecodeset(DP_ENOITEM, __FILE__, __LINE__); return -1; } free(path); return fd; } /* Get the size of the value of a large object. */ int crvsizlob(CURIA *curia, const char *kbuf, int ksiz){ char *path; struct stat sbuf; assert(curia && kbuf); if(ksiz < 0) ksiz = strlen(kbuf); if(!(path = crgetlobpath(curia, kbuf, ksiz))) return -1; if(lstat(path, &sbuf) == -1){ free(path); dpecodeset(DP_ENOITEM, __FILE__, __LINE__); return -1; } free(path); return sbuf.st_size; } /* Get the number of the large objects stored in a database. */ int crrnumlob(CURIA *curia){ assert(curia); return curia->lrnum; } /************************************************************************************************* * features for experts *************************************************************************************************/ /* Synchronize updating contents on memory. */ int crmemsync(CURIA *curia){ int i, err; assert(curia); if(!curia->wmode){ dpecodeset(DP_EMODE, __FILE__, __LINE__); return FALSE; } err = FALSE; if(!dpput(curia->attr, CR_KEYLRNUM, -1, (char *)&(curia->lrnum), sizeof(int), DP_DOVER) || !dpmemsync(curia->attr)) err = TRUE; for(i = 0; i < curia->dnum; i++){ if(!dpmemsync(curia->depots[i])){ err = TRUE; break; } } return err ? FALSE : TRUE; } /* Synchronize updating contents on memory, not physically. */ int crmemflush(CURIA *curia){ int i, err; assert(curia); if(!curia->wmode){ dpecodeset(DP_EMODE, __FILE__, __LINE__); return FALSE; } err = FALSE; if(!dpput(curia->attr, CR_KEYLRNUM, -1, (char *)&(curia->lrnum), sizeof(int), DP_DOVER) || !dpmemsync(curia->attr)) err = TRUE; for(i = 0; i < curia->dnum; i++){ if(!dpmemflush(curia->depots[i])){ err = TRUE; break; } } return err ? FALSE : TRUE; } /* Get flags of a database. */ int crgetflags(CURIA *curia){ assert(curia); return dpgetflags(curia->attr); } /* Set flags of a database. */ int crsetflags(CURIA *curia, int flags){ assert(curia); if(!curia->wmode){ dpecodeset(DP_EMODE, __FILE__, __LINE__); return FALSE; } return dpsetflags(curia->attr, flags); } /************************************************************************************************* * private objects *************************************************************************************************/ /* Get a copied string. `str' specifies an original string. The return value is a copied string whose region is allocated by `malloc'. */ static char *crstrdup(const char *str){ int len; char *buf; assert(str); len = strlen(str); if(!(buf = malloc(len + 1))) return NULL; memcpy(buf, str, len + 1); return buf; } /* Get an integer from a database. `depot' specifies an inner database handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the key. The return value is the integer of the corresponding record. */ static int crdpgetnum(DEPOT *depot, const char *kbuf, int ksiz){ char *vbuf; int vsiz, rv; if(!(vbuf = dpget(depot, kbuf, ksiz, 0, -1, &vsiz)) || vsiz != sizeof(int)){ free(vbuf); return INT_MIN; } rv = *(int *)vbuf; free(vbuf); return rv; } /* Get the path of a large object. `curia' specifies a database handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the key. The return value is a path string whose region is allocated by `malloc'. */ static char *crgetlobpath(CURIA *curia, const char *kbuf, int ksiz){ char prefix[CR_PATHBUFSIZ], *wp, *path; int i, hash; assert(curia && kbuf && ksiz >= 0); wp = prefix; wp += sprintf(wp, "%s%c%04d%c%s%c", curia->name, MYPATHCHR, dpouterhash(kbuf, ksiz) % curia->dnum + 1, MYPATHCHR, CR_LOBDIR, MYPATHCHR); hash = dpinnerhash(kbuf, ksiz); for(i = 0; i < CR_LOBDDEPTH; i++){ wp += sprintf(wp, "%02X%c", hash % 0x100, MYPATHCHR); hash /= 0x100; } if(!(path = malloc(strlen(prefix) + ksiz * 2 + 1))){ dpecodeset(DP_EALLOC, __FILE__, __LINE__); return NULL; } wp = path; wp += sprintf(path, "%s", prefix); for(i = 0; i < ksiz; i++){ wp += sprintf(wp, "%02X", ((unsigned char *)kbuf)[i]); } return path; } /* Create directories included in a path. `path' specifies a path. The return value is true if successful, else, it is false. */ static int crmklobdir(const char *path){ char elem[CR_PATHBUFSIZ], *wp; const char *dp; int err, len; wp = elem; err = FALSE; while(*path != '\0' && (dp = strchr(path, MYPATHCHR)) != NULL){ len = dp - path; if((wp != elem || dp == path)) wp += sprintf(wp, "%c", MYPATHCHR); memcpy(wp, path, len); wp[len] = '\0'; wp += len; if(mkdir(elem, CR_DIRMODE) == -1 && errno != EEXIST) err = TRUE; path = dp + 1; } if(err) dpecodeset(DP_EMKDIR, __FILE__, __LINE__); return err ? FALSE : TRUE; } /* Remove file and directories under a directory. `path' specifies a path. The return value is true if successful, else, it is false. */ static int crrmlobdir(const char *path){ char elem[CR_PATHBUFSIZ]; DIR *DD; struct dirent *dp; assert(path); if(unlink(path) != -1){ return TRUE; } else { if(errno == ENOENT) return TRUE; if(!(DD = opendir(path))){ dpecodeset(DP_EMISC, __FILE__, __LINE__); return FALSE; } while((dp = readdir(DD)) != NULL){ if(!strcmp(dp->d_name, MYCDIRSTR) || !strcmp(dp->d_name, MYPDIRSTR)) continue; sprintf(elem, "%s%c%s", path, MYPATHCHR, dp->d_name); if(!crrmlobdir(elem)){ closedir(DD); return FALSE; } } } if(closedir(DD) == -1){ dpecodeset(DP_EMISC, __FILE__, __LINE__); return FALSE; } if(rmdir(path) == -1){ dpecodeset(DP_ERMDIR, __FILE__, __LINE__); return FALSE; } return TRUE; } /* Copy file and directories under a directory for repairing. `path' specifies a path. The return value is true if successful, else, it is false. */ static int crcplobdir(CURIA *curia, const char *path){ char elem[CR_PATHBUFSIZ], numbuf[3], *rp, *kbuf, *vbuf; DIR *DD; struct dirent *dp; struct stat sbuf; int i, ksiz, vsiz, fd; assert(curia && path); if(lstat(path, &sbuf) == -1){ dpecodeset(DP_ESTAT, __FILE__, __LINE__); return FALSE; } if(S_ISREG(sbuf.st_mode)){ rp = strrchr(path, MYPATHCHR) + 1; for(i = 0; rp[i] != '\0'; i += 2){ numbuf[0] = rp[i]; numbuf[1] = rp[i+1]; numbuf[2] = '\0'; elem[i/2] = (int)strtol(numbuf, NULL, 16); } kbuf = elem; ksiz = i / 2; vsiz = sbuf.st_size; if(!(vbuf = malloc(vsiz + 1))){ dpecodeset(DP_EALLOC, __FILE__, __LINE__); return FALSE; } if((fd = open(path, O_RDONLY, CR_FILEMODE)) == -1){ free(vbuf); dpecodeset(DP_EOPEN, __FILE__, __LINE__); return FALSE; } if(crread(fd, vbuf, vsiz) == -1){ close(fd); free(vbuf); dpecodeset(DP_EOPEN, __FILE__, __LINE__); return FALSE; } if(!crputlob(curia, kbuf, ksiz, vbuf, vsiz, DP_DOVER)){ close(fd); free(vbuf); return FALSE; } close(fd); free(vbuf); return TRUE; } if(!(DD = opendir(path))){ dpecodeset(DP_EMISC, __FILE__, __LINE__); return FALSE; } while((dp = readdir(DD)) != NULL){ if(!strcmp(dp->d_name, MYCDIRSTR) || !strcmp(dp->d_name, MYPDIRSTR)) continue; sprintf(elem, "%s%c%s", path, MYPATHCHR, dp->d_name); if(!crcplobdir(curia, elem)){ closedir(DD); return FALSE; } } if(closedir(DD) == -1){ dpecodeset(DP_EMISC, __FILE__, __LINE__); return FALSE; } return TRUE; } /* Write into a file. `fd' specifies a file descriptor. `buf' specifies a buffer to write. `size' specifies the size of the buffer. The return value is the size of the written buffer, or, -1 on failure. */ static int crwrite(int fd, const void *buf, int size){ char *lbuf; int rv, wb; assert(fd >= 0 && buf && size >= 0); lbuf = (char *)buf; rv = 0; do { wb = write(fd, lbuf, size); switch(wb){ case -1: if(errno != EINTR) return -1; case 0: break; default: lbuf += wb; size -= wb; rv += wb; break; } } while(size > 0); return rv; } /* Read from a file and store the data into a buffer. `fd' specifies a file descriptor. `buffer' specifies a buffer to store into. `size' specifies the size to read with. The return value is the size read with, or, -1 on failure. */ static int crread(int fd, void *buf, int size){ char *lbuf; int i, bs; assert(fd >= 0 && buf && size >= 0); lbuf = buf; for(i = 0; i < size && (bs = read(fd, lbuf + i, size - i)) != 0; i += bs){ if(bs == -1 && errno != EINTR) return -1; } return i; } /* END OF FILE */ qdbm-1.8.78/rltest.c0000644000175000017500000001353510610627747013246 0ustar mikiomikio/************************************************************************************************* * Test cases of Relic * Copyright (C) 2000-2007 Mikio Hirabayashi * This file is part of QDBM, Quick Database Manager. * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU * Lesser General Public License as published by the Free Software Foundation; either version * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * You should have received a copy of the GNU Lesser General Public License along with QDBM; if * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. *************************************************************************************************/ #include #include #include #include #include #include #include #include #include #undef TRUE #define TRUE 1 /* boolean true */ #undef FALSE #define FALSE 0 /* boolean false */ #define RECBUFSIZ 32 /* buffer for records */ /* for RISC OS */ #if defined(__riscos__) || defined(__riscos) #include int __riscosify_control = __RISCOSIFY_NO_PROCESS; #endif /* global variables */ const char *progname; /* program name */ /* function prototypes */ int main(int argc, char **argv); void usage(void); int runwrite(int argc, char **argv); int runread(int argc, char **argv); int printfflush(const char *format, ...); void pmyerror(const char *name, const char *msg); int dowrite(char *name, int rnum); int doread(char *name, int rnum); /* main routine */ int main(int argc, char **argv){ int rv; cbstdiobin(); progname = argv[0]; if(argc < 2) usage(); rv = 0; if(!strcmp(argv[1], "write")){ rv = runwrite(argc, argv); } else if(!strcmp(argv[1], "read")){ rv = runread(argc, argv); } else { usage(); } return rv; } /* print the usage and exit */ void usage(void){ fprintf(stderr, "%s: test cases for Relic\n", progname); fprintf(stderr, "\n"); fprintf(stderr, "usage:\n"); fprintf(stderr, " %s write name rnum\n", progname); fprintf(stderr, " %s read name rnum\n", progname); fprintf(stderr, "\n"); exit(1); } /* parse arguments of write command */ int runwrite(int argc, char **argv){ char *name, *rstr; int i, rnum, rv; name = NULL; rstr = NULL; rnum = 0; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ usage(); } else if(!name){ name = argv[i]; } else if(!rstr){ rstr = argv[i]; } else { usage(); } } if(!name || !rstr) usage(); rnum = atoi(rstr); if(rnum < 1) usage(); rv = dowrite(name, rnum); return rv; } /* parse arguments of read command */ int runread(int argc, char **argv){ char *name, *rstr; int i, rnum, rv; name = NULL; rstr = NULL; rnum = 0; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ usage(); } else if(!name){ name = argv[i]; } else if(!rstr){ rstr = argv[i]; } else { usage(); } } if(!name || !rstr) usage(); rnum = atoi(rstr); if(rnum < 1) usage(); rv = doread(name, rnum); return rv; } /* print formatted string and flush the buffer */ int printfflush(const char *format, ...){ va_list ap; int rv; va_start(ap, format); rv = vprintf(format, ap); if(fflush(stdout) == EOF) rv = -1; va_end(ap); return rv; } /* print an error message */ void pmyerror(const char *name, const char *msg){ fprintf(stderr, "%s: %s: %s\n", progname, name, msg); } /* perform write command */ int dowrite(char *name, int rnum){ DBM *db; datum key, content; int i, err, len; char buf[RECBUFSIZ]; printfflush("\n name=%s rnum=%d\n\n", name, rnum); /* open a database */ if(!(db = dbm_open(name, O_RDWR | O_CREAT | O_TRUNC, 00644))){ pmyerror(name, "dbm_open failed"); return 1; } err = FALSE; /* loop for each record */ for(i = 1; i <= rnum; i++){ len = sprintf(buf, "%08d", i); key.dptr = buf; key.dsize = len; content.dptr = buf; content.dsize = len; /* store a record */ if(dbm_store(db, key, content, DBM_REPLACE) < 0){ pmyerror(name, "dbm_store failed"); err = TRUE; break; } /* print progression */ if(rnum > 250 && i % (rnum / 250) == 0){ putchar('.'); fflush(stdout); if(i == rnum || i % (rnum / 10) == 0){ printfflush(" (%08d)\n", i); } } } /* close the database */ dbm_close(db); if(!err) printfflush("ok\n\n"); return err ? 1 : 0; } /* perform read command */ int doread(char *name, int rnum){ DBM *db; datum key, content; int i, err, len; char buf[RECBUFSIZ]; printfflush("\n name=%s rnum=%d\n\n", name, rnum); /* open a database */ if(!(db = dbm_open(name, O_RDONLY, 00644))){ pmyerror(name, "dbm_open failed"); return 1; } err = FALSE; /* loop for each record */ for(i = 1; i <= rnum; i++){ /* retrieve a record */ len = sprintf(buf, "%08d", i); key.dptr = buf; key.dsize = len; content = dbm_fetch(db, key); if(!content.dptr){ pmyerror(name, "dbm_fetch failed"); err = TRUE; break; } /* print progression */ if(rnum > 250 && i % (rnum / 250) == 0){ putchar('.'); fflush(stdout); if(i == rnum || i % (rnum / 10) == 0){ printfflush(" (%08d)\n", i); } } } /* close the database */ dbm_close(db); if(!err) printfflush("ok\n\n"); return err ? 1 : 0; } /* END OF FILE */ qdbm-1.8.78/cbtest.c0000644000175000017500000006110510610627747013211 0ustar mikiomikio/************************************************************************************************* * Test cases of Cabin * Copyright (C) 2000-2007 Mikio Hirabayashi * This file is part of QDBM, Quick Database Manager. * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU * Lesser General Public License as published by the Free Software Foundation; either version * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * You should have received a copy of the GNU Lesser General Public License along with QDBM; if * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. *************************************************************************************************/ #include #include #include #include #include #include #include #include #undef TRUE #define TRUE 1 /* boolean true */ #undef FALSE #define FALSE 0 /* boolean false */ #define RECBUFSIZ 32 /* buffer for records */ #define TEXTBUFSIZ 262144 /* buffer for text */ /* for RISC OS */ #if defined(__riscos__) || defined(__riscos) #include int __riscosify_control = __RISCOSIFY_NO_PROCESS; #endif /* global variables */ const char *progname; /* program name */ /* function prototypes */ int main(int argc, char **argv); void usage(void); int runsort(int argc, char **argv); int runstrstr(int argc, char **argv); int runlist(int argc, char **argv); int runmap(int argc, char **argv); int runheap(int argc, char **argv); int runwicked(int argc, char **argv); int runmisc(int argc, char **argv); int printfflush(const char *format, ...); int strpcmp(const void *ap, const void *bp); int intpcmp(const void *ap, const void *bp); int myrand(void); int dosort(int rnum, int disp); int dostrstr(int rnum, int disp); int dolist(int rnum, int disp); int domap(int rnum, int bnum, int disp); int doheap(int rnum, int max, int disp); int dowicked(int rnum); int domisc(void); /* main routine */ int main(int argc, char **argv){ int rv; cbstdiobin(); progname = argv[0]; if(argc < 2) usage(); rv = 0; if(!strcmp(argv[1], "sort")){ rv = runsort(argc, argv); } else if(!strcmp(argv[1], "strstr")){ rv = runstrstr(argc, argv); } else if(!strcmp(argv[1], "list")){ rv = runlist(argc, argv); } else if(!strcmp(argv[1], "map")){ rv = runmap(argc, argv); } else if(!strcmp(argv[1], "heap")){ rv = runheap(argc, argv); } else if(!strcmp(argv[1], "wicked")){ rv = runwicked(argc, argv); } else if(!strcmp(argv[1], "misc")){ rv = runmisc(argc, argv); } else { usage(); } return rv; } /* print the usage and exit */ void usage(void){ fprintf(stderr, "%s: test cases for Cabin\n", progname); fprintf(stderr, "\n"); fprintf(stderr, "usage:\n"); fprintf(stderr, " %s sort [-d] rnum\n", progname); fprintf(stderr, " %s strstr [-d] rnum\n", progname); fprintf(stderr, " %s list [-d] rnum\n", progname); fprintf(stderr, " %s map [-d] rnum [bnum]\n", progname); fprintf(stderr, " %s heap [-d] rnum [top]\n", progname); fprintf(stderr, " %s wicked rnum\n", progname); fprintf(stderr, " %s misc\n", progname); fprintf(stderr, "\n"); exit(1); } /* parse arguments of sort command */ int runsort(int argc, char **argv){ int i, rnum, disp, rv; char *rstr; rstr = NULL; rnum = 0; disp = FALSE; for(i = 2; i < argc; i++){ if(argv[i][0] == '-'){ if(!strcmp(argv[i], "-d")){ disp = TRUE; } else { usage(); } } else if(!rstr){ rstr = argv[i]; } else { usage(); } } if(!rstr) usage(); rnum = atoi(rstr); if(rnum < 1) usage(); rv = dosort(rnum, disp); return rv; } /* parse arguments of strstr command */ int runstrstr(int argc, char **argv){ int i, rnum, disp, rv; char *rstr; rstr = NULL; rnum = 0; disp = FALSE; for(i = 2; i < argc; i++){ if(argv[i][0] == '-'){ if(!strcmp(argv[i], "-d")){ disp = TRUE; } else { usage(); } } else if(!rstr){ rstr = argv[i]; } else { usage(); } } if(!rstr) usage(); rnum = atoi(rstr); if(rnum < 1) usage(); rv = dostrstr(rnum, disp); return rv; } /* parse arguments of list command */ int runlist(int argc, char **argv){ int i, rnum, disp, rv; char *rstr; rstr = NULL; rnum = 0; disp = FALSE; for(i = 2; i < argc; i++){ if(argv[i][0] == '-'){ if(!strcmp(argv[i], "-d")){ disp = TRUE; } else { usage(); } } else if(!rstr){ rstr = argv[i]; } else { usage(); } } if(!rstr) usage(); rnum = atoi(rstr); if(rnum < 1) usage(); rv = dolist(rnum, disp); return rv; } /* parse arguments of map command */ int runmap(int argc, char **argv){ int i, rnum, bnum, disp, rv; char *rstr, *bstr; rstr = NULL; bstr = NULL; rnum = 0; bnum = -1; disp = FALSE; for(i = 2; i < argc; i++){ if(argv[i][0] == '-'){ if(!strcmp(argv[i], "-d")){ disp = TRUE; } else { usage(); } } else if(!rstr){ rstr = argv[i]; } else if(!bstr){ bstr = argv[i]; } else { usage(); } } if(!rstr) usage(); rnum = atoi(rstr); if(rnum < 1) usage(); if(bstr) bnum = atoi(bstr); rv = domap(rnum, bnum, disp); return rv; } /* parse arguments of heap command */ int runheap(int argc, char **argv){ int i, rnum, max, disp, rv; char *rstr, *mstr; rstr = NULL; mstr = NULL; rnum = 0; max = -1; disp = FALSE; for(i = 2; i < argc; i++){ if(argv[i][0] == '-'){ if(!strcmp(argv[i], "-d")){ disp = TRUE; } else { usage(); } } else if(!rstr){ rstr = argv[i]; } else if(!mstr){ mstr = argv[i]; } else { usage(); } } if(!rstr) usage(); rnum = atoi(rstr); if(rnum < 1) usage(); if(mstr) max = atoi(mstr); if(max < 0) max = rnum; rv = doheap(rnum, max, disp); rv = 0; return rv; } /* parse arguments of wicked command */ int runwicked(int argc, char **argv){ int i, rnum, rv; char *rstr; rstr = NULL; rnum = 0; for(i = 2; i < argc; i++){ if(argv[i][0] == '-'){ usage(); } else if(!rstr){ rstr = argv[i]; } else { usage(); } } if(!rstr) usage(); rnum = atoi(rstr); if(rnum < 1) usage(); rv = dowicked(rnum); return rv; } /* parse arguments of misc command */ int runmisc(int argc, char **argv){ int rv; rv = domisc(); return rv; } /* print formatted string and flush the buffer */ int printfflush(const char *format, ...){ va_list ap; int rv; va_start(ap, format); rv = vprintf(format, ap); if(fflush(stdout) == EOF) rv = -1; va_end(ap); return rv; } /* comparing function for strings */ int strpcmp(const void *ap, const void *bp){ return strcmp(*(char **)ap, *(char **)bp); } /* comparing function for integers */ int intpcmp(const void *ap, const void *bp){ return *(int *)ap - *(int *)bp; } /* pseudo random number generator */ int myrand(void){ static int cnt = 0; if(cnt == 0) srand(time(NULL)); return (rand() * rand() + (rand() >> (sizeof(int) * 4)) + (cnt++)) & INT_MAX; } /* perform sort command */ int dosort(int rnum, int disp){ char **ivector1, **ivector2, **ivector3, **ivector4, **ivector5; char buf[RECBUFSIZ]; int i, len, err; if(!disp) printfflush("\n rnum=%d\n\n", rnum); ivector1 = cbmalloc(rnum * sizeof(ivector1[0])); ivector2 = cbmalloc(rnum * sizeof(ivector2[0])); ivector3 = cbmalloc(rnum * sizeof(ivector3[0])); ivector4 = cbmalloc(rnum * sizeof(ivector4[0])); ivector5 = cbmalloc(rnum * sizeof(ivector5[0])); err = FALSE; for(i = 0; i < rnum; i++){ len = sprintf(buf, "%08d", myrand() % rnum + 1); ivector1[i] = cbmemdup(buf, len); ivector2[i] = cbmemdup(buf, len); ivector3[i] = cbmemdup(buf, len); ivector4[i] = cbmemdup(buf, len); ivector5[i] = cbmemdup(buf, len); } if(!disp) printfflush("Sorting with insert sort ... "); cbisort(ivector1, rnum, sizeof(ivector1[0]), strpcmp); if(!disp) printfflush("ok\n"); if(!disp) printfflush("Sorting with shell sort ... "); cbssort(ivector2, rnum, sizeof(ivector2[0]), strpcmp); if(!disp) printfflush("ok\n"); if(!disp) printfflush("Sorting with heap sort ... "); cbhsort(ivector3, rnum, sizeof(ivector3[0]), strpcmp); if(!disp) printfflush("ok\n"); if(!disp) printfflush("Sorting with quick sort ... "); cbqsort(ivector4, rnum, sizeof(ivector4[0]), strpcmp); if(!disp) printfflush("ok\n"); for(i = 0; i < rnum; i++){ if(disp) printfflush("%s\t%s\t%s\t%s\t[%s]\n", ivector1[i], ivector2[i], ivector3[i], ivector4[i], ivector5[i]); if(strcmp(ivector1[i], ivector2[i])) err = TRUE; if(strcmp(ivector1[i], ivector3[i])) err = TRUE; if(strcmp(ivector1[i], ivector4[i])) err = TRUE; free(ivector1[i]); free(ivector2[i]); free(ivector3[i]); free(ivector4[i]); free(ivector5[i]); } free(ivector1); free(ivector2); free(ivector3); free(ivector4); free(ivector5); if(err) fprintf(stderr, "%s: sorting failed\n", progname); if(!disp && !err) printfflush("all ok\n\n"); return err ? 1 : 0; } /* perform strstr command */ int dostrstr(int rnum, int disp){ char *text, buf[RECBUFSIZ], *std, *kmp, *bm; int i, j, len, err; text = cbmalloc(TEXTBUFSIZ); for(i = 0; i < TEXTBUFSIZ - 1; i++){ text[i] = 'a' + myrand() % ('z' - 'a'); } text[i] = '\0'; err = FALSE; if(!disp) printfflush("Locating substrings ... "); for(i = 0; i < rnum; i++){ len = myrand() % (RECBUFSIZ - 1); for(j = 0; j < len; j++){ buf[j] = 'a' + myrand() % ('z' - 'a'); } buf[j] = 0; std = strstr(text, buf); kmp = cbstrstrkmp(text, buf); bm = cbstrstrbm(text, buf); if(kmp != std || bm != std){ err = TRUE; break; } if(disp && std) printf("%s\n", buf); } if(err) fprintf(stderr, "%s: string scanning failed\n", progname); if(!disp && !err){ printfflush("ok\n"); printfflush("all ok\n\n"); } free(text); return err ? 1 : 0; } /* perform list command */ int dolist(int rnum, int disp){ CBLIST *list; const char *vbuf; char buf[RECBUFSIZ], *tmp; int i, err, len, vsiz; if(!disp) printfflush("\n rnum=%d\n\n", rnum); list = cblistopen(); err = FALSE; for(i = 1; i <= rnum; i++){ len = sprintf(buf, "%08d", i); cblistpush(list, buf, len); if(!disp && rnum > 250 && i % (rnum / 250) == 0){ putchar('.'); fflush(stdout); if(i == rnum || i % (rnum / 10) == 0){ printfflush(" (%08d)\n", i); } } } if(disp){ for(i = 0; i < cblistnum(list); i++){ if((vbuf = cblistval(list, i, &vsiz)) != NULL){ printfflush("%s:%d\n", vbuf, vsiz); } else { fprintf(stderr, "%s: val error\n", progname); err = TRUE; break; } } printfflush("\n"); while((tmp = cblistpop(list, &vsiz)) != NULL){ printfflush("%s:%d\n", tmp, vsiz); free(tmp); } } cblistclose(list); if(!disp && !err) printfflush("ok\n\n"); return err ? 1 : 0; } /* perform list command */ int domap(int rnum, int bnum, int disp){ CBMAP *map; const char *kbuf, *vbuf; char buf[RECBUFSIZ]; int i, err, len, ksiz, vsiz; if(!disp) printfflush("\n rnum=%d bnum=%d\n\n", rnum, bnum); map = bnum > 0 ? cbmapopenex(bnum) : cbmapopen(); err = FALSE; for(i = 1; i <= rnum; i++){ len = sprintf(buf, "%08d", i); if(!cbmapput(map, buf, len, buf, len, FALSE)){ fprintf(stderr, "%s: put error\n", progname); err = TRUE; break; } if(!disp && rnum > 250 && i % (rnum / 250) == 0){ putchar('.'); fflush(stdout); if(i == rnum || i % (rnum / 10) == 0){ printfflush(" (%08d)\n", i); } } } if(disp){ for(i = 1; i <= rnum; i++){ len = sprintf(buf, "%08d", i); if((vbuf = cbmapget(map, buf, len, &vsiz)) != NULL){ printfflush("%s:%d\t%s:%d\n", buf, len, vbuf, vsiz); } else { fprintf(stderr, "%s: get error\n", progname); } } printfflush("\n"); cbmapiterinit(map); while((kbuf = cbmapiternext(map, &ksiz)) != NULL){ vbuf = cbmapiterval(kbuf, &vsiz); printfflush("%s:%d\t%s:%d\n", kbuf, ksiz, vbuf, vsiz); } } cbmapclose(map); if(!disp && !err) printfflush("ok\n\n"); return err ? 1 : 0; } /* perform heap command */ int doheap(int rnum, int max, int disp){ CBHEAP *heap; int *orig, *ary; int i, err, num, anum; if(!disp) printfflush("\n rnum=%d max=%d\n\n", rnum, max); orig = disp ? cbmalloc(rnum * sizeof(int) + 1) : NULL; heap = cbheapopen(sizeof(int), max, intpcmp); err = FALSE; for(i = 1; i <= rnum; i++){ num = myrand() % rnum + 1; if(orig) orig[i-1] = num; cbheapinsert(heap, &num); if(!disp && rnum > 250 && i % (rnum / 250) == 0){ putchar('.'); fflush(stdout); if(i == rnum || i % (rnum / 10) == 0){ printfflush(" (%08d)\n", i); } } } if(disp){ for(i = 0; i < cbheapnum(heap); i++){ printf("%d\n", *(int *)cbheapval(heap, i)); } printf("\n"); qsort(orig, rnum, sizeof(int), intpcmp); ary = (int *)cbheaptomalloc(heap, &anum); if(anum != rnum && anum != max) err = TRUE; for(i = 0; i < anum; i++){ printf("%d\t%d\n", ary[i], orig[i]); if(ary[i] != orig[i]) err = TRUE; } free(ary); } else { cbheapclose(heap); } free(orig); if(!disp && !err) printfflush("ok\n\n"); return err ? 1 : 0; } /* perform wicked command */ int dowicked(int rnum){ CBLIST *list; CBMAP *map; int i, len; char buf[RECBUFSIZ], *tmp; printfflush("\n rnum=%d\n\n", rnum); list = cblistopen(); for(i = 1; i <= rnum; i++){ len = sprintf(buf, "%d", myrand() % rnum + 1); switch(myrand() % 16){ case 0: free(cblistpop(list, NULL)); putchar('O'); break; case 1: cblistunshift(list, buf, len); putchar('U'); break; case 2: free(cblistshift(list, NULL)); putchar('S'); break; case 3: cblistinsert(list, myrand() % (cblistnum(list) + 1), buf, len); putchar('I'); break; case 4: free(cblistremove(list, myrand() % (cblistnum(list) + 1), NULL)); putchar('R'); break; case 5: cblistover(list, myrand() % (cblistnum(list) + 1), buf, len); putchar('V'); break; case 6: tmp = cbmemdup(buf, len); cblistpushbuf(list, tmp, len); putchar('B'); break; default: cblistpush(list, buf, len); putchar('P'); break; } if(i % 50 == 0) printfflush(" (%08d)\n", i); } cblistclose(list); map = cbmapopen(); for(i = 1; i <= rnum; i++){ len = sprintf(buf, "%d", myrand() % rnum + 1); switch(myrand() % 16){ case 0: cbmapput(map, buf, len, buf, len, FALSE); putchar('I'); break; case 1: cbmapputcat(map, buf, len, buf, len); putchar('C'); break; case 2: cbmapget(map, buf, len, NULL); putchar('V'); break; case 3: cbmapout(map, buf, len); putchar('D'); break; case 4: cbmapmove(map, buf, len, myrand() % 2); putchar('M'); break; default: cbmapput(map, buf, len, buf, len, TRUE); putchar('O'); break; } if(i % 50 == 0) printfflush(" (%08d)\n", i); } cbmapclose(map); printfflush("ok\n\n"); return 0; } /* perform misc command */ int domisc(void){ CBDATUM *odatum, *ndatum; CBLIST *olist, *nlist, *elems, *glist; CBMAP *omap, *nmap, *pairs, *gmap; int i, j, ssiz, osiz, tsiz, jl; char kbuf[RECBUFSIZ], vbuf[RECBUFSIZ], *sbuf, spbuf[1024], *tmp, *orig, renc[64]; const char *op, *np; time_t t; printfflush("\n\n"); printfflush("Checking memory allocation ... "); tmp = cbmalloc(1024); for(i = 1; i <= 65536; i *= 2){ tmp = cbrealloc(tmp, i); } cbfree(tmp); printfflush("ok\n"); printfflush("Checking basic datum ... "); odatum = cbdatumopen("x", -1); for(i = 0; i < 1000; i++){ cbdatumcat(odatum, "x", 1); } cbdatumclose(odatum); tmp = cbmalloc(3); memcpy(tmp, "abc", 3); odatum = cbdatumopenbuf(tmp, 3); for(i = 0; i < 1000; i++){ cbdatumcat(odatum, ".", 1); } ndatum = cbdatumdup(odatum); for(i = 0; i < 1000; i++){ cbdatumcat(ndatum, "*", 1); } for(i = 0; i < 1000; i++){ tmp = cbmalloc(3); memcpy(tmp, "123", 3); cbdatumsetbuf(ndatum, tmp, 3); } cbdatumprintf(ndatum, "[%s\t%08d\t%08o\t%08x\t%08.1f\t%@\t%?\t%:]", "mikio", 1978, 1978, 1978, 1978.0211, "<>&#!+-*/%", "<>&#!+-*/%", "<>&#!+-*/%"); cbdatumclose(ndatum); cbdatumclose(odatum); printfflush("ok\n"); printfflush("Checking serialization of list ... "); olist = cblistopen(); for(i = 1; i <= 1000; i++){ sprintf(vbuf, "%d", i); cblistpush(olist, vbuf, -1); } sbuf = cblistdump(olist, &ssiz); nlist = cblistload(sbuf, ssiz); free(sbuf); for(i = 0; i < cblistnum(olist); i++){ op = cblistval(olist, i, NULL); np = cblistval(nlist, i, NULL); if(!op || !np || strcmp(op, np)){ cblistclose(nlist); cblistclose(olist); fprintf(stderr, "%s: validation failed\n", progname); return 1; } } cblistclose(nlist); cblistclose(olist); printfflush("ok\n"); printfflush("Checking serialization of map ... "); omap = cbmapopen(); for(i = 1; i <= 1000; i++){ sprintf(kbuf, "%X", i); sprintf(vbuf, "[%d]", i); cbmapput(omap, kbuf, -1, vbuf, -1, TRUE); } sbuf = cbmapdump(omap, &ssiz); nmap = cbmapload(sbuf, ssiz); free(cbmaploadone(sbuf, ssiz, "1", 2, &tsiz)); free(cbmaploadone(sbuf, ssiz, "33", 2, &tsiz)); free(sbuf); cbmapiterinit(omap); while((op = cbmapiternext(omap, NULL)) != NULL){ if(!(np = cbmapget(nmap, op, -1, NULL))){ cbmapclose(nmap); cbmapclose(omap); fprintf(stderr, "%s: validation failed\n", progname); return 1; } } cbmapclose(nmap); cbmapclose(omap); printfflush("ok\n"); printfflush("Checking string utilities ... "); sprintf(spbuf, "[%08d/%08o/%08u/%08x/%08X/%08.3e/%08.3E/%08.3f/%08.3g/%08.3G/%c/%s/%%]", 123456, 123456, 123456, 123456, 123456, 123456.789, 123456.789, 123456.789, 123456.789, 123456.789, 'A', "hoge"); tmp = cbsprintf("[%08d/%08o/%08u/%08x/%08X/%08.3e/%08.3E/%08.3f/%08.3g/%08.3G/%c/%s/%%]", 123456, 123456, 123456, 123456, 123456, 123456.789, 123456.789, 123456.789, 123456.789, 123456.789, 'A', "hoge"); while(strcmp(spbuf, tmp)){ free(tmp); fprintf(stderr, "%s: cbsprintf is invalid\n", progname); return 1; } free(tmp); pairs = cbmapopen(); cbmapput(pairs, "aa", -1, "AAA", -1, TRUE); cbmapput(pairs, "bb", -1, "BBB", -1, TRUE); cbmapput(pairs, "cc", -1, "CCC", -1, TRUE); cbmapput(pairs, "ZZZ", -1, "z", -1, TRUE); tmp = cbreplace("[aaaaabbbbbcccccdddddZZZZ]", pairs); if(strcmp(tmp, "[AAAAAAaBBBBBBbCCCCCCcdddddzZ]")){ free(tmp); cbmapclose(pairs); fprintf(stderr, "%s: cbreplace is invalid\n", progname); return 1; } free(tmp); cbmapclose(pairs); elems = cbsplit("aa bb,ccc-dd,", -1, " ,-"); if(cblistnum(elems) != 5 || strcmp(cblistval(elems, 0, NULL), "aa") || strcmp(cblistval(elems, 1, NULL), "bb") || strcmp(cblistval(elems, 2, NULL), "ccc") || strcmp(cblistval(elems, 3, NULL), "dd") || strcmp(cblistval(elems, 4, NULL), "")){ cblistclose(elems); fprintf(stderr, "%s: cbsplit is invalid\n", progname); return 1; } cblistclose(elems); if(cbstricmp("abc", "ABC") || !cbstricmp("abc", "abcd")){ fprintf(stderr, "%s: cbstricmp is invalid\n", progname); return 1; } if(!cbstrfwmatch("abcd", "abc") || cbstrfwmatch("abc", "abcd")){ fprintf(stderr, "%s: cbstrfwmatch is invalid\n", progname); return 1; } if(!cbstrfwimatch("abcd", "ABC") || cbstrfwmatch("abc", "ABCD")){ fprintf(stderr, "%s: cbstrfwimatch is invalid\n", progname); return 1; } if(!cbstrbwmatch("dcba", "cba") || cbstrbwmatch("cba", "dcba")){ fprintf(stderr, "%s: cbstrbwmatch is invalid\n", progname); return 1; } if(!cbstrbwimatch("dcba", "CBA") || cbstrbwimatch("cba", "DCBA")){ fprintf(stderr, "%s: cbstrbwimatch is invalid\n", progname); return 1; } tmp = cbmemdup(" \r\n[Quick Database Manager]\r\n ", -1); if(cbstrtoupper(tmp) != tmp || strcmp(tmp, " \r\n[QUICK DATABASE MANAGER]\r\n ")){ free(tmp); fprintf(stderr, "%s: cbstrtoupper is invalid\n", progname); return 1; } if(cbstrtolower(tmp) != tmp || strcmp(tmp, " \r\n[quick database manager]\r\n ")){ free(tmp); fprintf(stderr, "%s: cbstrtolower is invalid\n", progname); return 1; } if(cbstrtrim(tmp) != tmp || strcmp(tmp, "[quick database manager]")){ free(tmp); fprintf(stderr, "%s: cbstrtrim is invalid\n", progname); return 1; } if(cbstrsqzspc(tmp) != tmp || strcmp(tmp, "[quick database manager]")){ free(tmp); fprintf(stderr, "%s: cbstrsqzspc is invalid\n", progname); return 1; } cbstrcututf(tmp, 5); if(cbstrcountutf(tmp) != 5){ free(tmp); fprintf(stderr, "%s: cbstrcututf or cbstrcountutf is invalid\n", progname); return 1; } free(tmp); printfflush("ok\n"); printfflush("Checking encoding utilities ... "); strcpy(spbuf, "My name is \xca\xbf\xce\xd3\xb4\xb4\xcd\xba.\n\n\n"); tmp = cbbaseencode(spbuf, -1); orig = cbbasedecode(tmp, &osiz); if(osiz != strlen(spbuf) || strcmp(orig, spbuf)){ free(orig); free(tmp); fprintf(stderr, "%s: Base64 encoding is invalid\n", progname); return 1; } free(orig); free(tmp); strcpy(spbuf, "My name is \xca\xbf\xce\xd3\xb4\xb4\xcd\xba.\n\n\n"); tmp = cbquoteencode(spbuf, -1); orig = cbquotedecode(tmp, &osiz); if(osiz != strlen(spbuf) || strcmp(orig, spbuf)){ free(orig); free(tmp); fprintf(stderr, "%s: quoted-printable encoding is invalid\n", progname); return 1; } free(orig); free(tmp); strcpy(spbuf, "My name is \xca\xbf\xce\xd3\xb4\xb4\xcd\xba.\n\n\n"); tmp = cbmimeencode(spbuf, "ISO-8859-1", TRUE); orig = cbmimedecode(tmp, renc); if(osiz != strlen(spbuf) || strcmp(orig, spbuf) || strcmp(renc, "ISO-8859-1")){ free(orig); free(tmp); fprintf(stderr, "%s: MIME encoding is invalid\n", progname); return 1; } free(orig); free(tmp); strcpy(spbuf, "\"He says...\r\n\"\"What PROGRAM are they watching?\"\"\""); tmp = cbcsvunescape(spbuf); orig = cbcsvescape(tmp); if(strcmp(orig, spbuf)){ free(orig); free(tmp); fprintf(stderr, "%s: CSV escaping is invalid\n", progname); return 1; } free(orig); free(tmp); strcpy(spbuf, "<Nuts&Milk> is "very" surfin'!"); tmp = cbxmlunescape(spbuf); orig = cbxmlescape(tmp); if(strcmp(orig, spbuf)){ free(orig); free(tmp); fprintf(stderr, "%s: XML escaping is invalid\n", progname); return 1; } free(orig); free(tmp); printfflush("ok\n"); printfflush("Checking date utilities ... "); for(i = 0; i < 200; i++){ jl = (myrand() % 23) * 1800; if(myrand() % 2 == 0) jl *= -1; t = myrand() % (INT_MAX - 3600 * 24 * 365 * 6) + 3600 * 24 * 365 * 5; tmp = cbdatestrwww(t, jl); t = cbstrmktime(tmp); orig = cbdatestrwww(t, jl); if(strcmp(orig, tmp)){ free(orig); free(tmp); fprintf(stderr, "%s: W3CDTF formatter is invalid\n", progname); return 1; } free(orig); free(tmp); tmp = cbdatestrhttp(t, jl); t = cbstrmktime(tmp); orig = cbdatestrhttp(t, jl); if(strcmp(orig, tmp)){ free(orig); free(tmp); fprintf(stderr, "%s: RFC 822 date formatter is invalid\n", progname); return 1; } free(orig); free(tmp); } printfflush("ok\n"); printfflush("Checking the global garbage collector ... "); for(i = 0; i < 512; i++){ glist = cblistopen(); cbglobalgc(glist, (void (*)(void *))cblistclose); for(j = 0; j < 10; j++){ sprintf(kbuf, "%08d", j); cblistpush(glist, kbuf, -1); } gmap = cbmapopen(); cbglobalgc(gmap, (void (*)(void *))cbmapclose); for(j = 0; j < 10; j++){ sprintf(kbuf, "%08d", j); cbmapput(gmap, kbuf, -1, kbuf, -1, TRUE); } if(myrand() % 64 == 0){ cbvmemavail(100); cbggcsweep(); } } printfflush("ok\n"); printfflush("all ok\n\n"); return 0; } /* END OF FILE */ qdbm-1.8.78/misc/0000755000175000017500000000000011426314502012475 5ustar mikiomikioqdbm-1.8.78/misc/README-win32.txt0000644000175000017500000000431011426314463015137 0ustar mikiomikio================================================================ QDBM: Quick Database Manager Copyright (C) 2000-2007 Mikio Hirabayashi ================================================================ This is a package of Win32 binaries of QDBM. It contains C/Java APIs, their utility commands, and CGI scripts. See http://fallabs.com/qdbm/ for more information. The following are documents of specifications. spex.html : fundamental specifications spex-ja.html : fundamental specifications in Japanese jspex.html : specifications of Java API jspex-ja.html : specifications of Java API in Japanese japidoc/ : documents of Java API The following are header files of C language. Include them at source codes of your applications. depot.h curia.h relic.h hovel.h cabin.h villa.h vista.h odeum.h The following are dynamic linking libraries for the API of C. Copy them to the system directory or a directory of your project. qdbm.dll : QDBM itself libqdbm.dll.a : import library for `qdbm.dll' mgwz.dll : ZLIB libiconv-2.dll : ICONV The following is a dynamic linking library for the API of Java. Copy it to the system directory or a directory of your project. jqdbm.dll The following is a Java archive of the classes. Include it in the CLASSPATH of your environment. qdbm.jar The following are utility commands for testing and debugging. dpmgr.exe dptest.exe dptsv.exe crmgr.exe crtest.exe crtsv.exe rlmgr.exe rltest.exe hvmgr.exe hvtest.exe cbtest.exe cbcodec.exe vlmgr.exe vltest.exe vltsv.exe odmgr.exe odtest.exe odidx.exe qmttest.exe The sub directory `cgi' contains CGI scripts, their configuration files, and their specifications. If you want an import library or a static library for Visual C++, please obtain the source package and use VCmakefile in it. QDBM was released under the terms of the GNU Lesser General Public License. See the file `COPYING.txt' for details. QDBM was written by Mikio Hirabayashi. You can contact the author by e-mail to `mikio@fallabs.com'. Thanks. == END OF FILE == qdbm-1.8.78/misc/win32check.bat0000644000175000017500000000514310363132225015127 0ustar mikiomikiodptest write casket 50000 5000 if errorlevel 1 goto error dptest read casket if errorlevel 1 goto error dptest read -wb casket if errorlevel 1 goto error dptest rcat casket 50000 50 500 32 32 if errorlevel 1 goto error dptest combo casket if errorlevel 1 goto error dptest wicked casket 5000 if errorlevel 1 goto error del /Q casket crtest write casket 50000 500 10 if errorlevel 1 goto error crtest read casket if errorlevel 1 goto error crtest read -wb casket if errorlevel 1 goto error crtest rcat casket 50000 5 10 500 32 32 if errorlevel 1 goto error crtest combo casket if errorlevel 1 goto error crtest wicked casket 5000 if errorlevel 1 goto error rd /S /Q casket crtest write -lob casket 1000 50 10 if errorlevel 1 goto error crtest read -lob casket if errorlevel 1 goto error rd /S /Q casket rltest write casket 50000 if errorlevel 1 goto error rltest read casket 50000 if errorlevel 1 goto error del /Q casket* hvtest write casket 50000 if errorlevel 1 goto error hvtest read casket 50000 if errorlevel 1 goto error del /Q casket hvtest write -qdbm casket 50000 if errorlevel 1 goto error hvtest read -qdbm casket 50000 if errorlevel 1 goto error rd /S /Q casket cbtest sort 5000 if errorlevel 1 goto error cbtest strstr 500 if errorlevel 1 goto error cbtest list 50000 if errorlevel 1 goto error cbtest map 50000 if errorlevel 1 goto error cbtest wicked 5000 if errorlevel 1 goto error cbtest misc if errorlevel 1 goto error vltest write -tune 25 64 32 32 casket 50000 if errorlevel 1 goto error vltest read casket if errorlevel 1 goto error vltest rdup -tune 25 64 256 256 casket 50000 50000 if errorlevel 1 goto error vltest combo casket if errorlevel 1 goto error vltest wicked casket 5000 if errorlevel 1 goto error del /Q casket vltest write -int -cz -tune 25 64 32 32 casket 50000 if errorlevel 1 goto error vltest read -int casket if errorlevel 1 goto error vltest rdup -int -cz -tune 25 64 256 256 casket 50000 50000 if errorlevel 1 goto error vltest combo -cz casket if errorlevel 1 goto error vltest wicked -cz casket 5000 if errorlevel 1 goto error del /Q casket odtest write casket 500 50 5000 if errorlevel 1 goto error odtest read casket if errorlevel 1 goto error odtest combo casket if errorlevel 1 goto error odtest wicked casket 500 if errorlevel 1 goto error rd /S /Q casket @echo off echo #================================ echo # SUCCESS echo #================================ goto :EOF :error @echo off echo #================================ echo # ERROR echo #================================ goto :EOF qdbm-1.8.78/misc/benchmark.pdf0000644000175000017500000014574410523136326015144 0ustar mikiomikio%PDF-1.2 %âãÏÓ 3 0 obj << /Linearized 1 /O 5 /H [ 997 194 ] /L 52196 /E 51873 /N 1 /T 52019 >> endobj xref 3 30 0000000016 00000 n 0000000944 00000 n 0000001191 00000 n 0000001395 00000 n 0000001539 00000 n 0000001745 00000 n 0000002240 00000 n 0000002419 00000 n 0000002440 00000 n 0000003096 00000 n 0000003117 00000 n 0000003679 00000 n 0000003700 00000 n 0000004424 00000 n 0000004445 00000 n 0000004888 00000 n 0000004909 00000 n 0000005424 00000 n 0000005632 00000 n 0000005979 00000 n 0000006000 00000 n 0000006581 00000 n 0000006602 00000 n 0000007090 00000 n 0000007111 00000 n 0000007620 00000 n 0000029117 00000 n 0000051731 00000 n 0000000997 00000 n 0000001171 00000 n trailer << /Size 33 /Info 2 0 R /Root 4 0 R /Prev 52010 /ID[<21b37df8f836949f6a724722f5ba950d><21b37df8f836949f6a724722f5ba950d>] >> startxref 0 %%EOF 4 0 obj << /Type /Catalog /Pages 1 0 R >> endobj 31 0 obj << /S 36 /Filter /FlateDecode /Length 32 0 R >> stream H‰b``a``~ÊGw1`PZˆ¥ ˜A”Ÿ1ñ ë ÙÂmX¬€¢?L00|gØÍÔÃÀ ØÀÀ`•ÀÀð%øÉ†&†' }¢ÔV endstream endobj 32 0 obj 90 endobj 5 0 obj << /Type /Page /Parent 1 0 R /Resources 6 0 R /Contents [ 11 0 R 13 0 R 15 0 R 17 0 R 19 0 R 23 0 R 25 0 R 27 0 R ] /MediaBox [ 0 0 595 842 ] /CropBox [ 0 0 595 842 ] /Rotate 0 >> endobj 6 0 obj << /ProcSet [ /PDF /Text ] /Font << /TT2 8 0 R /TT4 21 0 R >> /ExtGState << /GS1 30 0 R >> /ColorSpace << /Cs5 9 0 R >> >> endobj 7 0 obj << /Type /FontDescriptor /Ascent 985 /CapHeight 0 /Descent -216 /Flags 34 /FontBBox [ -165 -307 1246 1201 ] /FontName /ADKHFG+Century /ItalicAngle 0 /StemV 0 /FontFile2 28 0 R >> endobj 8 0 obj << /Type /Font /Subtype /TrueType /FirstChar 32 /LastChar 122 /Widths [ 278 0 0 0 0 0 0 204 333 333 0 606 278 333 278 0 556 556 556 556 556 556 556 556 556 556 278 0 0 0 0 0 0 722 722 722 778 722 667 778 833 407 0 0 667 944 815 778 667 778 722 630 667 815 0 981 704 0 611 0 0 0 0 0 333 556 556 444 574 500 333 537 611 315 0 593 315 889 611 500 574 0 444 463 389 611 537 778 537 537 481 ] /Encoding /WinAnsiEncoding /BaseFont /ADKHFG+Century /FontDescriptor 7 0 R >> endobj 9 0 obj [ /CalRGB << /WhitePoint [ 0.9505 1 1.089 ] /Gamma [ 2.22221 2.22221 2.22221 ] /Matrix [ 0.4124 0.2126 0.0193 0.3576 0.71519 0.1192 0.1805 0.0722 0.9505 ] >> ] endobj 10 0 obj 578 endobj 11 0 obj << /Filter /FlateDecode /Length 10 0 R >> stream H‰”TQoÚ0~÷¯¸Çä!Æg;¶óXJ†2 ¶‚§J«ú¢Ð²®T#Aýû;§$”Áh§HŽåÜ}÷ÝwŸ3¸¬SXÔ xêôÁZ/Ø`ÞÿW ľçvgRnõlŒ&í^{ŽfU½ýÕt5$ZèÞ¡ÈþëîPüuÜŸÌÉxfÚúí†Ê+ÊëVû¶üM4½˜äq’Ê”òùå¬øæ‹¯Ó8qNf\F׳Âçà‹†(Ï¢Y~1êNB3}*¾ä0/~äñ­ÿÌrÏ~³¶DÉ`«°š ƒtÁ×°þøA¥x&wú\…Fðê8>8ÕXwOC®“¾Ý Î:hÍî ·«Å#ŒÊ¦¼+ë &庼¯6€Ü‘ÉõSF„±ò»‰(<#i²$Ò ‹ít)%Um+HBJiRº \J—µsš¾CUʽK¦ÕË1QºrçXJ vÛ±$lÛ³´Üe-³0s‡ZŸ£9‡&ŠÞMÑ|{W7«fÛT§d¥Ò'ø’ñ\{+DƵîUE‚„­ã*"w‹ž0ý6¬=aa¥: <>O8ÍìÞ-ãé÷ÓPg˜)z¦ô?Þ)YØôpÒ:ßþ`6gDé endstream endobj 12 0 obj 484 endobj 13 0 obj << /Filter /FlateDecode /Length 12 0 R >> stream H‰””Mo›@@ïüŠ9‚*F³ß»Ç`zh¥Vu‹ÔƒÓIå6Á*F•òï;P ÄN—]13ûôfv¡x¥2 9© (¥PäQ\äYRüŒ<’â¯_PI²`¼AëIAñÈ¡ÍáÏ¡|€¼lËïå©„¶ËlŸÝ/”%ÔÔgkÞÿËÞÅ­NRÃåPÆ’ ’T{í1ÄF±É·ÑJkž!n–B­Ïˆ‡ú 6ÇúÔ–u;:³Äé$:yæ$ônää œ*5¯sfËœ–Cià̪æWõP=AžFÍ?–𺅟i”#žé7ž¦0h|[D¿#kø`F[ölIIÌà¡©¢¯PGYqqbŸÑÈå¤føuÛ‘qÁíu<×$ëüóø<ûfEzóe³$£¶go mª n>½ƒã=l¹ÜÆå鮪÷‡ú›}ÕÜ&K†f;ž-55P ó£!©ékCŠΠ×k)‹tîåAóøAÐçù’ Î8äk‚ZhÊz||QÑèýê.„:7ΣŠ9dšÁ‘rî«w‚‡{E[¥'õ’š üoW¥B7>¬rz>:¯SWáû³t-Wørá—É×éæ2r¦›ÔL·0tô_P'6ì endstream endobj 14 0 obj 646 endobj 15 0 obj << /Filter /FlateDecode /Length 14 0 R >> stream H‰”TMoÛ0 ½ûWðÖfpùÛémi»Ê­‹íÐÃ[©µØr É[Ó_?JŽÓfëR,AZ|â#)AñÉ Bc ø¬4!iNSˆÓˆä9 h½Ó+Å65t+X¨®äZ ù…hù¤øáM)¡aÁø_\Çï`ôMàðÿâNCJ’CðÑp¸Oo§{€|=ÑWƒ½kæžYuCŠêfIF’p§nQ K.˺ej †k¸b:(YSö 36Ï,îOg³ï'Àd+˧‘Ï’W̰%Óœ¸B`ˆ¦C‚_•0.Ì36âø”RûÅËNUšÜpVý^qSÖÀšÆò£÷hKU¼óNçq˜šÃšo]rÖþÉšÞ%ÇvCbÝã{>]n±Nmòi`¾Óáœø{;|aG'„ìI‹^Ú<7L±–®ôžèb~=°pcÓ¯„Þ4lë2_Úª6\­:Õ2Yò}´jnÏà³ý#„$&Q€Õ(É.¿áNï­6¼õaÁ¥}C@²«Op¾¸ó! a|=‡›÷×>`åzÁ*(âpd9ïÚ@&ÑÉ3x(KˆHDBlmïú<ýÝO|xhÄ²Ä Ði7æãqÍw§•ÚÓšPJòx7OwR×;(Ø4RK×ÎÑãÆ=kÑt`u×/%ˆb7(¶÷C Üqke,™ÙÔíy2+|+Y¯¹Stœ;|©º5—ð«ÆGkÌÔ¸?p½;šËÂKC2 ,'%)ž¦YЙĖ„@oåY;H­o§xHñ†Ípí v ÿÄÉ í#€$J0Ÿ#waŽ5Ä™­ÈÞ2;pÇ8Jù 0åt‹c endstream endobj 16 0 obj 365 endobj 17 0 obj << /Filter /FlateDecode /Length 16 0 R >> stream H‰|”»NÅ0 †÷>…g¤câĹÍgCb@g`@L\Hp^»4 AÔêP©þ¿Ï­“–ç%,… ä³Çêáà°&ø|úU§*w£î2&Þ¯ÇÑ*—€”ŒzvZدǂÉx½È Ùê-½'}´_wó<^ç :&àÈmL$ClM^ÏŽ'pëu: z%è 8]—/ ×pwïàqIÚ…ÀË7™¨«°ºNËÇBÒ‡4#só? Šukv ï=À¾*ýö‡xËzŠ[ß{ß³†g"šÇ»(31<-Ð=3Ñ=0›ž-0<Ñ=Q¶k±<[`x&¢{dß&gy¶ÀðLDóÙ@ÑZ¯èž™èž ÇÌZ¯ž‰èžD¬9·ÀðLD÷”ŒÞšs ÏD4S@o͹ºg&º'Tt¦g ÏDôsá³@íi(º¿LÌ£ #TÒßZªà“œŠµÉ…vI¼áÖå[€£µð endstream endobj 18 0 obj 437 endobj 19 0 obj << /Filter /FlateDecode /Length 18 0 R >> stream H‰t“»nÝ0 †w?ç o’¨µy‚ C è$Ú}ý’ŽeË©²ãüüÄ;a³jØ…A¡ÀëfÐÁ¤‡o§0€çíiûµ®ØêP Y€KÇ&ðûçöÞOàôs1üTùˆ^¬)’÷‚½¦#3Åo´3r…ÚAjã!‚Êè×ïóãFðÂÁ_ØX…FPuwS¢™Ãÿ>þüXú0‘|fžº!yzøöpÙ)¾ Ô3Ã…]»buøˆ/Ö³JžøˆYU±=ÿPöID¢e™¢jÁº¿—uŠÂ)VF[Û©¦gqA].Y}ó/”Ö°D‚1[…„Í:Ì¿1„³±ìY¶Q.’«qk¼íUÇ¢®m%C±úW@¥¬«44_Úm_;‰ÔêÒ®œe±•t³¸AúX{'ɸ,†K»xK1¶C—õKœMÌ‹iïíìËpÛàO·x¯±ûxûü$ˆ’Mž‰S„S4i&Ná „ò°'âl7âCª>§0;›k¹„ƒÐ¸Ñ2×r ƒˆC±¹–KD‰Î™^ bl2gz a¬·®ÿ`åqÕ endstream endobj 20 0 obj << /Type /FontDescriptor /Ascent 859 /CapHeight 0 /Descent -140 /Flags 32 /FontBBox [ -121 -137 996 859 ] /FontName /ADKHNA+MS-PGothic /ItalicAngle 0 /StemV 0 /FontFile2 29 0 R >> endobj 21 0 obj << /Type /Font /Subtype /TrueType /FirstChar 32 /LastChar 87 /Widths [ 305 0 0 0 0 0 0 0 0 0 0 0 0 500 0 0 500 500 500 500 500 500 500 500 500 500 0 0 0 0 0 0 0 633 637 664 648 566 0 680 0 246 0 0 0 742 641 0 0 707 625 602 590 0 0 742 ] /Encoding /WinAnsiEncoding /BaseFont /ADKHNA+MS-PGothic /FontDescriptor 20 0 R >> endobj 22 0 obj 503 endobj 23 0 obj << /Filter /FlateDecode /Length 22 0 R >> stream H‰””=oã0 †wý vð(‰úë:(z@ \" CÑ©¸E³ô†ûû¥lŦsYé}Š”)E+2,M6C¶úS‘Ë€“Á[}™ÄI,™È‰$±ð&@ ‚X…F›da§E°á:àØ kK$i.|äê’fa%\ à‚ š ˆhx‡’˜AøNÖÙAYÆ<~ýݳ îfÜÔ9 +asfCMD"ˆ²Î&|^t@­#G5õ£ÒF—w•I#?ÓÀX>$ƒ&ùàÓå¤pòÿ¼)Ë\ÖåM½th¬ë ÓùSî­w:Ó[fXÅÞ#®SÓû ^»õÝvJÛ©ï_ËO¸´©”i`S-Õ"ÐR*×ý‡Ç¾|( Yï,sÁê2ªîiuùulÖîߨû%*Yî“´Ê8œƒª$­»Ùº’jhAüA(¹UKß ew{¼«H¹Y¥ÃÓØŠ0è.×»ˆiJ Ùet}¸‡DBª×+ò:$˜väëeüú­Þ'ÀówÙ€ àKfC=ì9¿G«å›WÅÚ‘¿Z‘'¾qõn&î‰&N5¿8t¸©'o{Þ(`;oë`{ÞºçÃCÙëòð¸oÛ@ˆ”µ|×-µ¤.ó?Fú¤5ñ2éa;Šœß È»ú endstream endobj 24 0 obj 410 endobj 25 0 obj << /Filter /FlateDecode /Length 24 0 R >> stream H‰|”MNÄ0 …÷=…×HX±ãümá£Yp« Xp}ìvœ6e¦ªÔÑôù}q;0$†_˜2ccNUAŠýj «À÷ÛtžìùyrÄ ÉãYᑪ [໓DŒì •#/ ¯‰JÀ” RB®0g@±)Fõøìº-*|ì …œáb÷1®wÌhèɘøsÕWÌ`èÝâѦ\_1ƒÁ1‘¥ÞǸÞ1£¡cr@9¨ë+f0tL«(r€¹ê+f08FbÆxP×;f4tL‘ÃM¹¾bƒc±6ã}Œë3Œ6d`ؾÏÏú±e&ŠŒ¹W!–†¹®kœÍ¬cµ}ë\°G)mh84,4—yŸl‚<$=|ˆ•0¤ÜgÈ#JT)†Æ–ÊrÚb’ØGmZcPœŒœ#Õœ‘d·TˆI›Cëñ¶®­¬µ0ŽÝ,vqìh9-­kâ[„¦å€[uUNÏ!Íôr!;> rž²Ì9Œº_¡=Ë}ß\?\6¬£ ¸ endstream endobj 26 0 obj 431 endobj 27 0 obj << /Filter /FlateDecode /Length 26 0 R >> stream H‰t“ÁŽÜ †ï<ÇL¥XÆ€ãf§ªT©+µÃ­ê©ê¥Ú¹´ï/Õ d0ÕîÌ!øÿ?lãkœ'àà¬+0ÛWãBä] yÚ»:A˜QC8‰ÀIá$r˜« ¡žBVÄN‚‚îc'Q2„ ‰‡Ð‰à¼îc'‘Â\eˆŽÀëÓáœé<äûCˆè @Æ·RdÉÍšh‚"¸ÈSMPDd(¤‰&("˜€#V¾wò.4ÐE¸ y"š dpÓIš0ˆâåe) ÅÃÏIwÙâᳮϺv›û0Ï÷p3[5Y®ªEù GEºB¶„R>£·õnððÿþ4ß¼¬TäÒðâP~—Õ–¤ Q”®?yaòâñD¦ÉË“WzÄ%µêxùQ?›´_ýÁc±U’Ê"ËÕ¦v€åëuûr©¿ ¦ìê€3E[¯fy–wi²nÝZߨöé±-ç'«^·÷v=7KÕbN‡³õM ç9ßÞüºÕõéö¼#õþ½\{çJ’ï¿=]é[>VÃ$Ÿ³rÙÙöH¦djöÏ/¹ÿåè· endstream endobj 28 0 obj << /Filter /FlateDecode /Length 21406 /Length1 30692 >> stream H‰|V pTÕþî½ïm $²‚yË#AHB4D„ðÈn `Ÿ»Hénþ ?1I#¨Ó†ò×¾P¦X„–ߪ(¼¤¡¢0t*C+ëÔheDÑj¦­yýÞ&a Ú¾›³÷œ{Î=÷|çœûò $¢ e÷ÍÎÉ­(/Gpufe]¤aBÕÑ ±­•MÆó“§îo€žVÓð`Ýåñå“ÿÐV>¸tEMϩӹýHmu¤ê”l»HÏqÏèZ.x[zžâ§<´¶®qùÙíçR(ï$-_Z_Á±íyÀb͵©‹,oˆû‰Æ³O{ã¡H]uaÚé ДÅxnk¨_Öȸù4%¸ú†‡«j§?ž $Ó§'OýôS¬¯†PÏ p.vSÇœ«Ôù8_Sk‰à#|ûYJúe'ëü§ÛÔY#G‡‡;clûw[ð)ŧ¤fÒB<,¼IhÃýø!v‰¸F‹#éÅß“˜Š{ñ0þA>„Fá×TL£ïW…‰9ø5á)œq~‹8x‘„*T£†>wãW0è#ŽáM- èt܉r´à8®ŠR±NÝBÑÛ ¼‰w¤’V~Ì@V£M~O>‰ž= K° ûÅu‘$.ieÎ0g£³É9åü§b&ê°/ãÇï9®]d‹÷•¡šœFg§ó#ÎÁ"œG«ãx%š‹Š1ôƒÄp‘+F‰ZÑ 6Óχr!säj¤jS¿Qç´<ýiç:ÅÓF0 ¹˜€ÉD\N|ÑóZæf#†ÈŽá }Î5b‘h»ÄAqX|.óätù±¼¦ªÕj“: ë‘oÞîØÚñ§Ž+Ng®sÄá½ ÿD Æ]“Q¥ÌIÑ~Ÿ'-bvÁrâX [° ;X™6ìÇa"z§ñG|ˆËÌG’Hwˆ{Ľb’˜'Ö K<ÍHN2GŸˆËRÉÞ²¿Ê1œHKe¹¬—äV¹WÚ²CPeê¨zO}©Ý®¥h†–«= ­ÒžÒjoéóõ%ú*}‹¾Ë3$né¿þðÍÈŽ„ŽšŽˆ"Í™èÌsuÖ;ç™-ðv)x8zÕ@öÏPöf6F¢€yó³§bÇlÌÅT¢–7æ!VÊ­•‹ñ1ü˜([˜×'° ›±»ˆt{t?^ÄQVÿÖð5üçØïs\ÄGøWð58¬mœH‰ÌD31T c.Ɖ‰b¦˜+ˆ*V§^<Ì±Ž£Ul¿`~öŠ6ñ¢8Å,½%Ή…#5ÙW¦ÊÑr‚œ"ýr6GP6ÈuòI¹M¶Écòwòmù®9L\Ãí-í]™£%£D'ú¨Åfæ5ÞÙó"QÈ"‡7ø¸ªÑWy† 3n)LÞ²Å-M¬»µ29_6É ªãT®6C¾­Ý­.ôHÑŠéj_æ+ñïàBácoe%LÏX `lþØ1÷æÊ½û®œ‘ÙY™#†ß9,#}¨9Äg ¾cPZêÀ)·÷Oî×·O’·÷m‰ ½â{öˆóèš’Y³(lØa[Ë0§MËve3Â…ÈM aÛàRÑ­6¶Ž™·Zвæ¿, :- nX ¯1ã³³Œ€iØgü¦Ñ.æ—ɯ÷›!þãgÄx-#&$Rðù¸Ã¤Ôú [„€]ÔTkÂ~ú‹öŠ/4 «ã³³ïE¶9»ÈlˆŠ¢‰"ÆÈ¢@~T¢G"£²KLÀ.6ýn¶JDªì²ò`ÀŸêó…²³lQXiVØ0§Ø½3c&(Œc{ í¸Ø1Æ"ZŒhÖ «µÝ‹ŠpfB•YY´U$äž‘”iO5ýöÔG/¦dgµ‹¶9A»ga»ÀœàQ”8ÍÑâf¿?äžÖ§0¸îfóTeR®hYë {gyðf­Ïý …è4;«tVÐǨÍ@«á˜Œ! S‘’à Ý5f'àj3஄vOsŠYk-³X-³Vø^XRpÔy%Ú4}ö¤T3ñ§EûÁšµâPqQ|«&;+êMêÌtô¶Þ]LBâÍLõ ]Œ‹™»£îNµp#2‹Ù"¶Qi0’ iËô1îOõX•chÆ'$˜ÑEÌ_Øòæ»…ÐÓ½¦a}6‚yé³[W"]+žtïpY·]n´õݼ™iávJ\!KËÈ&Æä{²³šìR³ÁkØ¥LÊ‚ÜÊÏaÊ}>·Ê-í¨ `7—;e©/  '3d˰«9Ñ­Ižëjš»57¶‡M¶óa¸ŸlÉvŒ½½ýûjómÑÿÿ¨«;õ¼>#ªééVY0#bµ¤f„­ÖKSÄ«hYE¦Qd…­H»Ó\a^ÓŠ––Z p7¤vçDKª]ЪLª=ª3vß J•¡NN¦*r¥³ÍÒòùA#`…» ×µ2&&¹/FF÷AG€ßz3ùÿçç=¿ŠÅ~Ó#·{º–äØ.Zˆ#jêµeÎym6yžÅ"Ïð=ˆ%òY¬&õäÇc…vÚ¯¡üSÎ{ܽ´¯&] …I©Ž´‘ôÒ6Òã¤&Ú¶‘6ÓG‘ëÇÕz”ë"A?å|ÎïÆiߣEœ×êó°˜|-c «)˜Nƒ)ÏæzAÜz a|s(×S.ãÜÈ=yz<ÖPΧn4}~w¦¾éúnçºöJ÷Už;„ó휟Óà\'¿² ƒ—ñLжü‡órâºÂø¹ó^¯×»8Œ˜C¤°¥ ˆgð`%ÝoãÆ»—`ìˆm£a»ž„h¾<ûšÄ¾$‡oâ¾U¹*À¶¬k1ö¦„1ˆžƒÍ—À•-4÷عZ=‹õm!2ðõXåµÉÈF_D{Ç¿Xš‰;I¦ôU hø6«ÕSÛƒµl@ìu9ñ°…ÖÂŽÙÐIÊgT$owñ®K~ùx¾bÿ mâ¢6?0°‡ðy¯_e˜c»mëAü=‰³GÌjü"Êî—‡³ÇéE €|w9ÎÀV°¼ !V‹0~Ç-ÇÇ(Ç Çæ þÅNìò:ÖÑtìÉølîìÀóßÓ@ ¾øi–¼¼áØe[½¹9Æ8vrⳑÇpýçñ¼¶M» £æ ‘ói•“lóvÄÅyªW>¡¥Ò}ÔäwShS¸–¿Lcœz„~¹mƒu­wƱ7¡^gkºü·–ªr`áðïû x¶1Çs>Âý!Ò´í4O ÁÞ»¸þ¾ë¶9µ~+-à5«Ç¨ÅÙ‹lmá½5.ÒTã%ô98Ëò0fÈ ÇWçY]iÕ\©Í˜ƒO5Z/Ú<?Muü•õ£ç+õW8kØW<ç#ªf_iG1æyR Ìm\ÂõQZ`”cüvpõöô>=çœAÅøU…3M>Žu½I¹N\7âþ<-†M–Ãap1‰1ª‚k^ûm(ÎJÎù3œˆ!-í|>þìCL< ‹QP¡‚Îż‡QeçäóŽóóʇàsÄoöÜëäÃI<ã0ÆÏu“/Õ”þH–ãՋiÍ­+p® ‚‡‘K—©óž¿ýà"Ú¸uAš¢\B=1|K=!íuñ®ŸÔш^·•y²ïmÿÕˆ,\ßäß{ʵ¤ÀtƒÄw½’BÑШÚÔ æ‚pû3 í•Èÿ6P¢ÀÆÜMð×Þ%9”’^£4è= _zÍÎSk›ûÌøà‘Áëƒò[Í]}`¶—™æ/Ä^|Só=³»ÏìïW.0ÃKò¤/‘R î•,ÑM¶è¶Ÿ‘~TÛg&@õ_úÌ[L³ž1ï´Al¿Ù¶§Ï¼_dÆÛù>Ç´ÖÛë¥õñ¼ úgí}fhZR nP ¤Á=€åá„l Š:;ã·ñ3 LZ2_ZF¥  N~p4½’PÇ—a‰–¸†¹®Q ô‚ph#­ ÐR cÔ¨{âš=œs¢¡Ï¤ÎPg¸Óê´;cU†*ÕV¥]«Ôè`è`ø uÐ>;¨QC¨!Ü`5Ø ±ªBUá*«Ê®²‡bU±ÆØ/-Ä5é{]‚ÖVw‰ |ßZœÉ_Z}uhnë¾bÖáÖ}554.òô§päJDc»Ï!êŸýP7?×Íoêh‹®ASš›ÒŸëi§©Pœ‰Ñ÷£_OL¤‘GÿÃÄÿå#–«>mPyÍÒ:Wß—ü909Q<¹¦|\¨i±cÿÂÉ…{‹»ÇÈ©Éä–”g€»f,™±„»Pä¸+ÍÁlWáÞ…“‹»Å±lWÍcà@JîL&›wâ“L&E²9Ù\Ÿ¬oF>ܺ3ÒœÜÙœ„…ù¶yg$²3’¤Œ´|k& ì×™pɲŒ¶|k—ôõlÔÔHI´1äTXxÊWe…ñJ+^)­ŽD|®¨·ðÚ:‰³ô ²¢²Id4"$Á©Ø¨Ýˆã9WÁm䆹1ŽáþaãÄÒ"xyÇ[2M¢Í"ÉŒ»ÐM–pˆ8˜yô`Cóë2Ï>sàоW×Ó3áÑEõý÷§ÕÒGG7ƒM×.CÇ™ñ.gv/enUÊ ¤±“v¦„,a:‰N²“éÔï%÷2‡ÉÃÌ)â4yš9¥·hõY©Ý¦KàD8ßMXÁ:?A¸²Þ )ËãÒbVI–,¢`h¦0²„»°àÂÓ¯&]?Í<ÒÜxð=3öÓ깫¿S~î»#×UðMÿ‚ŸÐj«CÇt#º¿ ŠN!‚€I0pߘ$@É4PiR 馄iÜô “®ÕtÌD˜.±üƒ±ÅH:2<‹©™Ç(8¿àBଃ{àžšu@Í">‡5sPÍ…¿álƒê›ð#ôg܉µŠ¿ £1LœÜ-Úˆ€$-HXæÖ±=ì0{‡Õ ³cìev©<<$Ø)hÕz°3Ö›úg¯¥Ò#h ˜áì…¡`À]ÀÐùOÈp~ùU“I²²e5µÁot¨oVü°‡çtd½Ï[»¥sWóqƒÈ%㸄ìÉ3âæ¯Iè¢È.¿À/ OJ[ïê5Q»ÉøIüÖÍú;V¢ØÑm"ç<†*Ã:CáŽ6ŒÆ1ÆSĄۄ ]â¨K+è«â ÇW_ï÷54ÜnôýþF|ÖxþѼ.3ÊB£Jî9D5znQâc¶ÏÍê Bת‹ë:.I4)²eŽ79LЉŒ›4|Ž-!D›¦ˆF”½$ô—ɵô5}в—Ù-» ®,°¿Ì2Š$°Gâ»7 ‹C%Ž"«‡ÿóº}Ÿ, <*È/t |8$çÓoñûÂ!'ˆÈôþ³êýß_NŒö}0püÔ¾ýõßâã‚§·œ|gëË'6¬é¨YéòK²˜ÛRvzâÝQ=m·Š2ATW½}¤5_rùBÅO­©}á™]ïtŸAع¶c­ø±zE”n*R¡X$…Ä&©SB'³„D1 5J–,ÙdY’DDÊm:› ™—™ÚÌ, ˆ2'‰g›ÐÃö³Ÿ°X¾(°¶ŠÕ±I¢K1Ò²ˆh©•2 ·½QêÆ„O’ò@ I‚V‡¨ˆD\Ü!&ÄqqV¤DM,v æE¬—t„Ÿa|-•ü|oŒŸGU‘*ü£†¸ö¨¬6ƒ¹ •òeîá/3lˆaùDfñe,Èo@´x-¾ ÑŸYæÌ à7"sLJ~JìèÇ„f‰õjYˆN ‰CE0ãrÿúirRæy†ÙÐë)mqé)íÊ£µÛÞr-Ùÿäe§ŒyöÖ¢Ù¹ \^ohçÒÎc§[BM!Æm-éñ”™¥öÎI4h¸ä- ÝÊ+©©Êƒ>U¾ýݾå+Š 2¼ÞäüQÖ¯Ç. z½E~›Õ›©ÓÂÔw°º·¡ úÐÓ@8)W]án²7¹oR~`)†ÍÏcɼ¬â¬Ê¬ÁuLmÖ†`]ŽšÖæÅV+©²/=]“ܧ§ü}]‡£ÛA8 5ÆSÙc4^@Ë4 Ëèj:B«è!Ø,[½cøÊÉ:²Zר‹è¢º]?ºtŒ+9wrMaL><ʪ‰ð£œB¿xc’♚¦fŠÕÌž™¹95å ö)v=\G4iv²ÛÄ^ãUcIBmn…­Jç¶•?"(}VöùYÑïgÙdüÔÕŒ½O 2>~Â%T5›:LÝ(°ýe9~VU€Ä})BªHLŒqZWU#A$9ü«§Š×:µ²–¬Ö6j#Ú¨¶GÛ¯Õ2ÚÇŒ1¦;yÂyú*¢`}™,Š€Ò¥åóa¤º0Ä ñèNå¹'­ŒQÿE“™…åFR=íë÷~ëÁÏ”N\Ø3¼Z¹R¿¸½õ§¯5/io8ÑÕ;ÔMêç¼ßr¬éè_l;7÷ù¿u~^qàé‹kCÛVíÙ×¼®¶éëÐÁMí]]/okB>ÝŽ¶äF[rƒxK~6?®À“—ž(ñ§W²I+<éõÌFOmzËæ` [GÕëH“‰ä±M33ù”> åìãu‘Äh"‘¶ÖNÑÀ7†ÁÄ—MÒ:Gؤic<íDæ%«éFdÝ(ÝC÷Ó£(´ðܲ³wÿ- ñ¸àt¢”}ˆžgÖfÚ’B.œáNò¹yïüäàß!wñc(v>x³ólñ쬅Ãü’º7×(w£Ñ­[ºŽ­YûÉ®B³rRù½¢(]g[üä’ù>WšU°¥oÌ âÚûÏœºðöék8Ýza<¢z€ºŒäË)ñ÷úÈ1†ó ËŒ›2RÆntPI‡WY¦ê¢OTA'xT.àŒnc˜ÙsÁ¢EÁ`qqê:ÙÙ%‹UŠ‚9‹Š³³ÇŒÅAT}PýAßâá=¨O¨;À\àšü¢dϰW•öJg=¨êí‰ïrpz§Ã!DÁAlà"Ç9€Ý¾Upˆ‚à° ¡Jp9Ëy½^‚€¤Ô–&¡\R:ŽwQ ´C/ˆv'eu8¤BfÓÌt3*æÞd-ð.MÑCD΀õ3Éö7¶ “÷m­½K!nº!Ä SÀ <>…­> ~Élå/_fB!|Õá#t˜L\Ò5¹ØÉGè"’ ®/ ε¾Ø€ÿ¹T‰y16´(¡ª2;öuEM¼¥ü@ÄQwþõÞòÒR‘MÔàœÁÅYE¥¥¥õ䇱M8™V£¹µQW¤€,0(»KÔŒTž•š 2ÊùrNTn-㱩T´h¡vÒ²E”<] ÁÈ5ðb@,IYì#’â0Q ²qk#\Š!%#åê§ë–qhbŠƒs½›‹Ð9QŽÙhľ.¡°W‡¿Ú7MÁ´ƒLB‡9@ƒ8@Íð˜C3Øàšº÷“-D•<£­AÖ½âä°B<¸)XM’_Ý;yêÆÊ_ûc⮼`và8-/w–¼Ú·sŽîùÓýG©«×½Ôôþ*Úpz{©Û¬:–‘;~øìƦ¼do¬7v%-­«÷ð9tÚ~FÕ õ9ÁuY®§klõÎüv} ßIaòô‡ÄCÆÃæ~DÏyŒOÑ+é–—¨b;u„:¬;‘pÁ6f‹ßL6“$IŽZ@Àc² >n'‚,T BTèha*2Ï7i@œ –[Tåäôð]Y0ȆjC¿A% i"–Ë–¸1^rJ£ÒÒ]‰þ‡• 4L< \È„Ó)sª´€ÂØx¸½Oók^МŠï<¡çÍ“Ì$¸§yÀ¤:¶¨PZ0¿f÷™‘¿üì…ï§;”OLJ•ëÃÀŒ3ÕƒÔ3±³ÿÞñ†2¨lUΟ;ðço”(ã#0<ú9l¹4¥GÒߤ? ȯË.ç,x(ùp!«­¤;'WΪ=c9ç%‰gŸ¬KD¹†C·á?l—kl×ÇçÞ™Ù—wwfg×;ë}Ž÷ýðck0cØÇ.éìÖ, ~4ZS³ãl"¶@©!B¨ÁMHi#hÈZAU«ŽZP+ÑF<‡”4uQ”¤˜5=wlc*Uëï;æüî9ÿó?ØJò­Œÿ²Òm‚$DQ j†UùãØ¨Óêµm‘–Ñ„ÂÁp Lk–f±&ö#Ý(ŽáÖ–vSQ6Ñ=m4ñxÌ& V\¢]E5øöxn(¶¨)ŽrA5˜ðƒ³;Ž\_Zù»ƒç «VÇÊ"ǰ£êþå!ȧý@åY G^¹a¿yÐzÔ|Üúªû÷—n-ÇPîFFa™dÙ f%»Ê½Žiuw˜:¬î¬)kͺÝÇs£Ï“ädµ[k¸~J¶ù„J!%4 ?N Nð X \QÚn—´ñ4U‰Sãn’}QØ•.Mó^É›ôÊÞ&o¿wÈ«¥¼<,ho7ÊI'pi Ï{E´Ncìñmó¤%ØïWŸHËîA–2T&<:º¢©’BÉPWˆ ‘£K^W›W¥¢e"¿ ôÁ1‘Ÿ¨@3ˆ[MÕòÿhá D4'Ô±«eÖ2XK­¨oõ0Ôü´À2Ôƒ‘¬óèÇl?sÄ]}ûÀÔÝ@°oc[_ÏîÙÒ“¨ú=·hEÉä’ ‹“ñò,;>eúû¯Ã‘¿+4Ÿ}¥ðžäG· )±s$†³Ùgó-8›(u].{’}†Ír;mƒÜ€í§ÌqVׯ¢W¹×m÷YZÏ®„ã¡%>ÉËüÏð9p­a£ÏZiMY­$y5Vdý‹1-Š^ʇ zÚ‡?žáïDH›Ž¦ÉøÒ^omµ‚õæbegÀ3VäöÚàùâR =и`kìÖ<_˜È?ÂI$hn%CìLâ&ºU˜8¨þÍâÇPnbÞµÕW4·ŸH}›v³+VhŸïìK.~½°èµŠHlÞ! H!]SKii᳃‡ Þ|¹p­*¦(¡8óZÔOüüÞÑ PÌ$õ7yù:öûš¶SÓËîÒœ`ÏDߊ){?ú~™QaÌö²ôQªÐQ:&v•¤ŽŠ0G7ªbÉl¡OÑç@3sØ G1Ö® ¥>þtXO1ÆÒ@@rd¬ÃÒŒRö»ÈR—„¥n–MÆ›|\Š'ãtSÅGqÃ#Ó•'jȲEª(NäIמ˜AV«z0U]¤H¹ž3„ÊÂæp4¤/7vS\.E ]72Åøn*1×¥(u¦z$¨PT(êD€V—“eMbêæ¶ï{u¡eÊÆßÚsmóæ«{Î]™Wóî\½0¹<Q®ï½<õÛÑK¨îÖ_°Í¯ÞyØ}èðÔí©¯§NÝ;q 4ØÐ >Ü—íí½ŠZnßA­Lúí¥ùäp 5ð+6‡lò|P!O 6ñˆO#W–ùÜérŽËx2¢9£÷eôÁá”Ø%^ÿ)2¼(‰I‘s()ÛªQF£)Ï3P™é¯FMÕ¨šdàbÒ_ óµ|ž¸’‰ðÉS)ÈDb¦­ÐtfÂÈ5ƒ Ô2DK$V|ÌÁîܚȮúp;Þѳ$„ß,ëÄ=Û"ÉY¿±p°SM…gŒ%Kz ƒY)¬gCK7±ãJ¢yj!ú`MTQì.ËŠÉ¿>Åû%`ý.Æ…¯Vñ¥ŠâtðõLYs‚Z æò+Õ­’ÍIÂÄqÆ´I~áeD·ÞÑsä'…nÉ–>µ®Z™FëëuhÄ„“d!‘Ô›Hc™Ž÷±x R}+ñÙçVÅGjoaÍž'¢‚[é·Ž¤&Gê,¢¢Dë˜v™áÝdP¢*x75*/\güÈø™qÒÈ,75™6˜¶›ö™Ž˜~oÒjŒ² Ó®4ˆùlChR[‚–âxsDÆ#–"!mÑñÛÌiž‘¹vxâ§¡ÔE,Ȩ́å.C0v ¡[ïj´Ã–Ù mâˆý¼ý*ŒAö!ûˆý†ýžµ“¸ÝkÔ–>)¤”zâDtæ0¨æì[Æoÿ,ªüö7ÿœlðO&³K«â±£À"V6¹5¸ƒ,…q¥r>³7DtdEû4ЈQ7/¤èF¹‡»ävˆmÅØ¶aL£‡ã FðÙq ͳ±4C³Å Ž“|:‡¨C‘vÒÅ™ß@| ¡šíÅÃPò)C»á”1,+Âí0-ú`¿„r¢÷J‚çôÉ ÄCAÅmTœŒ;3ZjÕ:È“Á@X$¨3ÔBíLMÔÎ /½ ð/¬TT`øçhÍæ €@{‘ë¥hœM Qt }Ó»¬|Áò­…u»ÌŸŸ(|‘\ûߟ­HífÇ'»˜!%\9¹9V”˜Ä|z»}òímó4Š¢_ßG?H¬­h®~êS¹ç¼u°ëY¶×¸ÝÚã<À0î·ö;O°'ŒCÖ!§Ùâö€= ³ïµ-@”“{¬¿Ø‘æEÖàOëÀÝZx ^›vù“vÙÞd§íc‚ö$6œäÚD$fÚüÈŸqáì9q9´_Ž YÞ%¹’®&W¿kÈ5âºçú—KO¹ÈMn²<\†\´k}Nfí4·| ¯ê¨7™Ã¸ª?ä2=˜½¨Y`mcÆÆfI#RŠP!¿,“8 îâÕèô®šêÌ6®ªi}°áùþµM»,UÅžŠ:`»~²oÉB¬(e=õ“Ìèƒ}Ù°bö¶ÑŸ fp¾[`fø: Gy¨¹³Y³VXíÅ49ó¸ön-^c^c[ëÞIïdèvÀuÆÓ^4\°\.Ú._/9.».yþÃ~m°ó§)Ú~Z§wÞ¬ddæ C'™v3[oòFɘ4vÿËw•7qÝá}{XÒêØµ´²¤•V‡×Zk©>‘±ãÅ€œ`1E&Øø™Rè@0¥„£´@B'¡)ÇŒ›Bè'6±qiÔÀ´C˜IiÓ”ÀLM‡éÔ´ $@‹Ö}»²¡ÉýCowÞŽfgß÷û.rýºü£‰s`Íõ?¶‰gä3òëò:ùÃÝ z ²J)’„š•§jVyMòµ®”Nç4)ò“—rBmuIòóä¡ïµàJÔ1#]0ƒgw ä:Ç Så%Hßëm¹MdRAV—L¾ÉÄDÕ ]nÕd ¹‚[ãm< Á5">,¯q&èGÔþˆÃ€ÓýWÄXi…Odýø>À7¼ó™üÀêŠOÏ= Õ¾Æ/}÷é7ŽwÏ%&nž:Õ¶MÖD-vè(nüm1˜î82Ü·«*\„`ÈKr/q"îCæ Õ€“J³ð]fmö=Ë/‹½Æì¨:n§ƒCáÁØûU_£†Óúj4ØuÔ1Ê ãQ"¦E`Ø+¤•`(*QFÚ’‹$âxÅ‚~‹®¸¿¢ÂiAHšô’qR" r\‘¤¬õÆP¿ËE(ÌO'~©5÷‹ºV²Ï-æ‘K+ÍfGé5•.‚XèòÁ8ì’ÄñW"†ˆ´èÛűOüP¼)j“" Uª fBZzê^ËTF$!¦éÞIhÓ锘1¥Çº‹Ëj%„bMi#V†–6‚¢¨Ñhç`s! tù,¿]˱2& q£qEX…@>ª4ŒÿG¼"ôѧŸ?7|~ï óÂî\Öí)ÎZ`¹]·Æie©y»Û7Zì…ßO/ÙócûÁ¹“õß\?‡˜¸üã•›™@ý+ÃÛâþæuòÏÕ–ÜÚÞ³ =æ§,õõ‚?,éþí'^ÞYà *^·}zÿdh>HIâÿná?Vj¨1H¬ä\N4º:‰U†U®Äz׉K¶Kö߸þ ‹µöNÇ(tv²ìTƒ8‰Ø€}Ð :Qeïİ3(m„/±F4µ›Òb^`x^Œæ®àø5ü~/ˆÿƒÿ?Í“>ÆWÂ8ÏkÜ‚‘§p©ébî~«®kúa :‚70І( ïI_³dn7÷˜Ïšqóš’hvÙ Û`Ⱥúgˆ¢KýLcP5'!úªúÕÚ¡6åGLk;BÿýÞ !åŸÜ©ÒªG<^ £Õi#PcZãS®@Ö¨W¯Å= Z$Cí­[3ÄV PT%²¸!s>7 á³ sÄU¹œƒ 6ÕeU=u÷ðwŽK[îO¬”ïþþÖ»½µµa7|`¬ú­Ÿ/ßüðƒ–ãIJ­é[&¯­Y3_(é:ÖsQ~x`7Z1%ß9¹¹fM]QYíª±s« ÂeÐòsiA þ þ‘[èµø"¶‰mrÄßrÞÇ5•x9[îlÀX‚°c.ÆUr \·—;ÂMÃVÄÍnܺTʶCã2d§(“`©$ ÐÓ 1Á Hê1ˆ+ÕÆNÙ¢” ‰0G™KBÊ2wæÌ'!÷ÐÔ‹P*§d˜é™˜Ü dáQßW³_”:M–†o¸… ä›e‘püé%'róò ÷?—ä눉ôU0ÌÿÏÊá½f ÃÑ †t‘¨®Ý ÌfEUR FQa2ÀòöPsôá°¾&‚“ñv/ð~,):‚ò#°"ê½Gƒ£Û±ÁC I È1°ñB9zQʦâ}q´'èx2ŽÆã_SæqmKïëH·°vøS¯Sj|v@ËO(VHØÕÁ…P@`š®Tð*‡[žýåþUd¦ÆÌ¶™ˆFK—kgÁÁ–ñÈ0+c(‚ºaB5€×Á¢¥ƒwøÅ* ˆÿåºêc›8ïðû¾w>ßù#g_ü™óÇ]b; 8¶ã'€/KB Z‚ihHÚ Ê ŽZ… Ñ6U”‘¬E¬…?í«ÛªI Ú-0T˜J7¡UK -cZ%@¤­:5M51¨_ö{€ºI¾×ö½'Y~žç}~σùêXk'ùž¶!ÎáÄ}qùòj<µ|URÖ¬Ô£ŸÍè=Þt 0î)‘Ê‹ïw0½G♌,;¥ûµLk¬ª)Éð‹Û»î5²Ëï½gPׯ€ù0øÃO€ù:×Nf±­Î¾Øóν±C±c1~ÐýŠ“‚Éíq»<¼Ûí G¡ˆKøDaž2sæÓd#rÒ!Þu Æ\”(8ˆùe)zÙ¾è²Ý Çð[6ŠÕ8€ž`Ô$VKÇÊŽ2³÷OáÆ—Oì¬Z)ß»Ätè“/´lô¬„ïNvžºœÿ¸Éò—_ü`·Ÿ]I|¤üÁœ¿wct‡Ð0bq;ôŽÛ%ù‚¸?i /DrâsëÿÚ•PëªØnï_×' &ã­µZ˜÷Q5J¡ImÍveH!Ü#Ñã¢(œ L®10 ÁÜ-î éÐU9†Ìs•)Ðà[jOE{eå\%¬«œ¬¼VÉVNfÍci—{äœ<,Ê×å¯e#’5øÂÈgÈHgš2®žPIŠU51¨X4 I[Ú,Ý–a Ûm³ËiÒ…êç[Ñ3¨ êϲB"¦}ÇNG5 m¨xŒe;ýëa7÷ ³¡pr~PÓRâtp…›…²BG„aÌÑ=šŠ“¬j}¢¹«¬{tëèQœÅþ=[²é*¿>oºöΛ›6¹\eåúMýٶǾ3øÛg–fVw}·iïS¯þI9¼fGH.•Š`Uª9ÙûóU­ÛuÔ¬¨ø­²¶e»ÖfO ¨ÛæþÍ®"8ÝMM‘5Öæ±½î¬g?BÞk ö‰6“Ùf*Š ™%Q”¬VŸmDBø§Z‘oâ©ñhžvOÇà™À^­IŠ4,J¬"ÕHšÔ^È ÃÒ¸4%]—¾–Ì6¸5 ¶u  P:òŸÙ¦²½py } tZJ’éB½L¥ 1³D 56”õbE€%Äy{q)ì]¨Œ+[7|b®L™x‡ %ŒoF†þhù°¯€È@û"%„3–/ô‹$.‡¼Ž:ÞÚ0Úñ‹éÿ¼³ñÐêT²Â×’^DÖ>4°mźƒ†«ùU?¦ë—?Õ?o^¿¹¾è¹زØÒLþ—ïß¼zæÉçÿþÑ9ê+Ë禙vгŠNiÀ)â]oŸ`Dw”cF®n©_Ú'HcÒ¬4'E˜æTŠ.\¢¹,# ®ÁíxŸÇ×1Ò¶~³òæ¸Qnœ;Á禸ëœq Wõs9ø;˜ë/i–[T¥´¿ÍPMŽó(–Y^Y/*áa ”^ä3”PÄnH—$Y )ü¡D ÐÌë€bÄÆuúí÷¾Á¶‰—ßnª®ZQj[×´'Ý9¾÷-ì*Öo`rål½kiëŠ%K*ŠÍþº'ö_¾8 šÛ šÛ š“Qú\K´bŸ¬•Z¼Kð•ÊY´#_®ØXš³˜¹¬ÑÄó0bÃdŸ<"Áy½äç¸aø« w)¼‡PIJÁAElITI·8&‘žÖÊ f¦aÆMÓ#…W¡à<ÔÕ< ~Õ*Ù#~ t¤Za Ø| °¢Òÿ—UYÈd™J‡Ø2sx›„²*ìJ‘ ‡³<qú† Øwºæ÷)žá… ^0BÁdÝí1¥N{my„lÄ»R©Fý¼'õF÷øÑ×:G’-Mõ;öýpÛÎã¯2üÅ~WÏh™sÛžÁ–O¾:Üß¹™ØÅò·O^þô^|wg=×YPßPŸÐÏ´*MÁ ã’’€ÙAØb‡ä ‘íÞÝØ/:{kÆ 4‡o7°Äb À]¼ª :_•JÖJ—AÏKŽcNæŸ2d6¾xawã«ú—gõ¹üé—þ/Ë÷â£¡Šƒ]ÛŒÿveSï5Ÿ>mMcï¡=ÙkØuì =‰Q„˜„áKh6okò6ÿ ÿ%åu…uñ$‡±”sž)æ‚h€&ðZ "ëÁ‚%k6…7w«ýê>uDSgÕ9Õ(Âh˜ [þ€äŒü_²«>¶‰óŒß{çÏ|ØçøÛΓøÛß]ìàÄ$à˧YM‰ÉBB˜LJC£R‡$ ”vÐòGÒi°j ªÚ?h·¡•¦0DÕ­ÓÔIt¶ÝGþ±ŠÄ–¥ÒÐ:MØÝóžÓd,Jôæ}ïì‹ý<¿ç÷±€¼R GÒRäèÚ‹^SŹªs+4"èyš¤é4=KSô诫&Ÿo¥!ÑÀu€J¬Î0“™ÄPÄe¹~º`Èb Z¹~"d ôƒùÅÀÉ¢¨Ùua=æ¹7EK%ú¿ÉT™Ñé,lìdᣞM¡7ß¼}!;½E5y˜px×$uy Ð'!áx|äÍî#å¡Áͱ ÀÚ* ÕçHPÄp1«ØBÝ#Zˆ$±‹øDÚ<9¹ùµñ7M·©šÝÍžæ-MRS[RJ¶©_¯zÝ8ÛD…§ØémS.—/Ú~°Æœ6“=æ%3i^ +%o\GÄ5+O‘Ó­ãꞃ>}ïh]RGºÊʔ约2,6ÉMLÅb14š:é¥ÅQ%Q—1ñCñKQ)þ´;Õ‚<·à) ™åü1Ð <ÅŠò\áAÁº\ˆãW=\–­h6ƒbßÔË9ŒEf“*¼ªÂÑ&|S­ª…» ÅM“/ËÕÒ%¢ÅðÆÉ^Æé!ñ°„ð*›]¥U{í*ë¤ÑÚ4Ž#ÐàÈ5 u2”¢ÚËPŽ£J§‚=JPä…£WVo+4o•MK󀱯Ûp Æ ?ñÎОmÍ=õBº¨j–²»»¦zCbºhhŽ‹‰ÖN ÓÿÔW÷ÎD±ƒó§RÁ º9yú‰ó}ÅW#¡T*,(ö¶¶Ÿ6©B}Ë ‘‘*EB‚‹¿W¹*N©Ðߤ`¥ªÊ2`.3.êf´sZ2¡í³Ÿ¡(]μX±H8ædÚ1ë ¸d5rÉòP!l"ó2|ñ2XÜâúXÇ(ïヿj w¶ó|Gç4A[ÝÏþ>\”O*ïvòáöŽp¸³ðYù£Ïku¦TŠ ’;šãQÀÇyøü ˆ–zûô}ôîêAF¡×Ó ”Ì0ßÓÓ&8)t,;I*L$© ™jV¯Sš2_Ã+X¡VTù=ã€ÉköšÊ˜2^aVèhªl¾W^.˜Lý‹’uÈtË´dZ1)Ó dœy8|mR™ÈS’C$[ã`íI{f=”–ö 8†šTíšöÏøçü”Ñ•›n˜i˜k W8”†fâÂE p™| z~ofïxB©<외PÀéÿbWáVÌy"¿,ÇVˆ>ºã¿:£ƒÜªƒàªÖÑ­šV(÷8  ÉÒ‹ó©JÐzÁý”ÚüxüЂ(A õÿnôÏ츃25=E"÷—_1:Ŷ¢vgDdBÉ( ëBZ?c×™ÈînM÷­b —J™t:Úd™ÑS©[ñRØÌâEc» G&"&±Pd¨¹ õ"ÊiM‹Då|%™®œAƵ0¯‚è¡ <`Ȱñ³nBoìžáÂ?öòa§7Ö§¼ûŸ«ÕzÀF}@1±Ö¤ð~† Tw¨ëD m—Z|º˜Ž¼àºÐHj=UÛ»¯ª½_Q¡R§0›¨Úêë­’Äóg·[¬@&-I­?Bµ$-ÐÃ÷ 9½}ÞNÚq?Í3Ç,1+€4ÆÅô0CÌ £dHÄDŽæj8‘»Ä]á>äÔcÜI޹47ËQ~/ëÏéy/ð ~ž¿ÅÊ«§ùžLðCüOñ¥ÇGæ"K‘•ˆBqEz"C‘™ˆ2¿–$¤K)aújÉu\‚KáG&’cÉÙä—I‘¤a3Ÿü4ùuRE'Óp ’¸¨ÛWµ“ˆM¼ÈØ–öÁ­þ@˜íd´É¢|e±bÂ*­«ñîqÚÂIo—É×¥ÿ8ª°¨·_øÎ¾uoí;)õš«›„bPhG¾a¸z^*ºA¬öõ>ßitÆÅb àwP— †í9<úüöýo…ÞšJè³gÇ;¶n-Žõ.tå•cÛFÎ_åh3>“#шѼñõ Е»Rà¬ý¢tJ*'«¡ÜÎû*µ¬/*½&,”¬,¸7ååë³P’–ëd'!À­uyÁÊã"|p­Ò•Û +Åñ¬,'t¾€Ûk/Ä×ËŽ ^XužU6‡ZëPÛ°ªØmv³¤+ ß8÷jF¡dΣÊj%ÈŠ‚Zsîk]Ú *~ÙRmP•ÔdÔ&Þ}>sb;k/V íæñìy!ÖV¤Û¢m[Dê²q÷ÔÈÈ·ÞxºØ…‰…Ðk§{®}¿ø6>X2Óº¤ \ú pé„8# ’HmC›5• µñ ºÜ2%QcÔ,u…ú¥”(ä‚=I-]ïÓSD*{ÁNÿ++G½’ÿ)ùpdSúL*Ë0ªÒÐÄ ÁNW;³Â8L´°XÉÊa¤/¯–=¸¼p§ˆ,ÊdQ„ÀÖH)UÖÿq>¨p¡ÃøîµBñúØìLvòµêãâÊÒî@¦?ÿ™’¿ýÓÒíÛî}ßlKqZÑ ŒRÈùJò;%¥Û "ÉiH:èSªkêNªàXe9æIúØð”ö:yÅŠì?7\òålxnk^‚­a_`)‘•Øôù®ÖØ(®+|ïÌììÌ>fvwfgfìû;³ë5žuüÊ'žàÒà°ÍckRA!Æk‹’ØjÀ!Å&­À‘ELT©)Q[¨iŠXj¢”-N_TQ+Pë´j+ -Šb»gÆ<”FªVš=wæ®vî9çûÎ÷Eº#C‘™È­È|„ñDF#7#$à|äþÐÔ"æX°ü¨í¹ûHµ$Hƒ© ­ EJuÚeO9ÕlJ§WîÄ¥.¸”3‰¸Ì‘¹oúÚ>-ÍñŸ Òœ:€xÏ—lŸ'™"©™°%)õ¡béþ ¯@YÂ@×¾êjÛ½üZ汭Ýçz†{Ç;_«õ‡rÍ‹îæ\nõNâéžS¯÷íÉ·&/sǾí/ÎŽ|<:°uËâ‘2Ÿ²f%?jΓë~óÁµéÏÏ|dùž*ð={ Yô#·K9 ¼­\T>Pn(Sþ­0¶€?ð~àwªFj‘ˆ¤a‰¨3k:êÄNÓ •{gmö’hGÌûí.®—äF¸ î6·ÄÙy.ÊéܸqŽ»ÊÝä˜(‡90G†£›)2W™ë Řú߯F÷…"t0{¼äx›Š‘zN%Ô{¦¨oÿìì\^7]QaÎê`Ý×…K⇚éUü’Rr@ t€ïØüTð΃4ƒ}„¶í»¯ ¿d‰L&µÓ+ðÿ"¸ ?]3V|rÛcå+k=¼©Z«Õçê,\.蹺š@™‹G®Lžjh©¯Œ¯Úø\cÿÏ{®•$ׯO‰ÍM fvû»_'¯£õïh‰ÚÄzךīîauÌu2õGË8ñ.|ÿ§ŒLÆãÃNVt:Ù2½ÜO’Yv»ž}•}ƒ}‹ý)û{ƒý{—uҬijf)– ‘¨MïÖ‹úy}ZŸÑçu;Ò=º¡/ß²n²XŽB@韗¯t”;†Å“"!*ƒòM™Ø wɽò <‹%Ù…å„”<…?1$)´×ç§}v‰&÷–Â{Å“Q¦°Ï&äsòUù:ì½-Ó¼Œå_ƒ¾õî¢6­ÍhdTkÐí !!’à›ÔG"æãˆ‡Ã1ÎàÚ¸yŽBœ‡‹q9kÙÍ q w‰xÅ„f_a?2S¯ÍÁ8µ¥IZ 06M «Ï ¶"·}KÑd³è›‚BGð=ó¥•fa²ÖV ‰rœX¶fð1!g:={‚¼ðø[/öôgŸœhlÞræàîÕ™`cÙÉ}]Ï?R1òƒG6nýÅÉãZ«E¼ãÇGºZK¢‘ÈêšvmÚûµ–ÅÉ×^*4®ÒÒrXˆ¼´õжoÂý¦–^ú”¸mÓPõáSNŒ¢HIÚ…ÜwÌÝæ¦ÜŸ³EAB'AI_!žE4raß…Q7vO;&éƒ~sFz‘à áŒ0-Ì´ „‚Ö±gçžY…B=Ðܶ$E¥7î{-F®­4IZ­ö&ªkjkp¾ ë‹®Ë7u3ô›/¿ðÊ÷{ëÚmÚâw¶/¼ýÔ3/Ÿ¸òîà.¢¿EX× 'xtéSê';ÿÁÈ%NB J 2~ʹÙ5èv#qÐ×!8€¤Mý]qˆ"ç÷Û}ðÒ?ãx‹“öƒ€ø¦I|0nž%e„ÛÂ3á[a AÐ.†‡Âg`9f<áÑ0ÁzÂ8¾„ÿ„8zny®Ãá,–^¦èYÛ€ÿežöBIp; †ˆ ÕŽ,·xŸx%ÙFÓu‡²Éö;Xò?œéx9GË$›Zá6ÍL˜¦Z“]«Æ‡¿µ­xºùYÜZ_³jñ}qÓ;ƒíÙH¼¼ðÝý‡Þ=†»rÕd‹÷‹¥ê|#siçs›7]çj ä!ƒÁ¥Yª†< =ðOC\+n„aû1ÿ˜ÿ¢ÿ—vÆ`ðÔÒQ£ñ‹1»ä÷3v‘aì¬ Šý !+Ù’a`Ò:Ýãžqž'ÆãÚѬÀñ’&¡…ÓÌ£Ì7˜cÌc»É`ØnÕõ¾‹1>ÇOó$?E Wñ(>§± O½†€Ð º…æåAmh‘h$èù Ôø¤¹BÀ‚V>ïµÐ•GJh©¹9h7°ð ¼’ížY²Y2ƒ,4h!îçàµä嗪͕'0 1ˆµ½Òq÷¯¶Q|xU‹°øÃšÅQ1ÿy¶‰X’¤…„Âq­¾¦&ºªì‹Éв69´zi–¶CËð)ã¹g@t¥¶ªß“m¬sD±NG§Ö‘ÞíØ­ 8ŠåCå7$‡¹©êT éBæ çëÒ›©ÓéÓ§ªjŽ”ƒM91Ct`^òtðÑD¬#Š2eˆsº;¸ˆ²¢#bL-º §’1ø6ö°i-¦jjJëg"Ë:2éô0Ë@Ä8S©aYeYJ$“ý²‘’PdÉé`™ŒêHIð<˜8ŒèT2™NkN&“Ö(”‚ªM&R–£jŽ}‚%XE§pöÂ9«S„d„cCpr”C‚2Ù&ÐMD°QÔ‹ˆ<º„G+ïã#€rAA ^«*À–P2(ײú}`<|Ë3)Ò*ØW‚l6¨ ÏöLÿÿëQs3c’íþBÚ%_¦Õ”9Qýpe –‡-@Z]PÇkÒ%Žß^TëZñ{j•Æþþ¬·j-îijQçëï~R·xÞ“yÜðK…á»mZssHñ)ßÐã0›› O,8‰ ½d½" W9ð +¡K*ñ>ãDF_Cw ±ÝÂîØúÍ016G´ûÚ…-±Îø¶Ü– :—«°3Œn÷ ‹Çb>Ÿ/ñzKJúuFÔu¨v8V!½$&PÙœÏîehº"Çñx–w•Ð4n·YÞlÚÔ§²¢d2¥Ž¸ÝGŒ~»àoôQé4Qžoà7ðäU󼬉!b”˜!(Däƒ ”þÊÊLé 2¢L(׊W” ÿe¿Zc›ªâøïœSnÛÛn½íº®Û:Ø£íF÷r ”­{°Ž996NŽÌmÂtˆO@tfÓì ¯á‰1(1HŒ ú‰ Dcˆ5†CD·Îÿ½· 1<ŒübOïïžÿyÜÓsþÿó¹…ûþ,2PLkXú3ÆÈïŠ ùÜSYvøúÎú¥E>õZTªþs’…^êHT±Í‘ªÐü©~+¦C¡Ð_Huž>áŽ7¥:qCR'L¡Ý©ÊQJH{éâPõ„êê.Ù#ï«…Rjß|fÔ=.õZÌXAaMô9Þ8`f¯Œ¶dyÙ‘úxž·Ê£¤Ïuå´Æ7µÕW½Ÿ,]K×À¯x.w9ý–ÆÆŒžïâ{æåD£“Õ’yû\±Ç“â`ѨÑ]\=ªÅðÇ4»Ä·áp—oÈÌ1 æãéK‚T7à”øåt—Ëp•?é ít¹¶øe§ß/—˜d'X~?<¤–Ÿ„KŠz<6‡-¨;E'¤Þ1/÷¾˜•…2§lŠÝTÂ`’¸7NЬœbN†í;ìíÂ~Šœ`WÔMæ}(Óò°Ø¤j]k5ê#£Ö­ +ÍÆ’T¦õD6agU $¨Bi©‘˜¿Û”Ð?R¿Ø]õciwN22ɨǸhñ®*ƒŠòE¬ZUÁRö‘o_b³Î¥×u±]…ñëWwoŒ®©ñT 9y+ZºãûÓj«É4çd§¤L_`˃óŠ¥HÄÒ=uåÓeíËC%uåù–4›Ñ|æÿ½¨ÐHG\K¹ÄñÝ/ÂÍF mùn~„‹ Q-šE—x^Œ‹ýÒ^ÛqÔz™..[SŒÂlåVòÞ»,VŠ}­0uPj°“ƒßäŽQw¨¡è|Æ­)½L²C¯L ·r“ÍÆ^Ó(ƒ½×1zˆÜÏ%Ïv• …1ro‘°W‘så –;äC²¹Gî—wÊcòUùgÙØA—OóÅV7Õ¤‚ÌØÉZ )jõxs:T«B™ŒÑ£yº—TnÄ v³<5´yU+mËçßO¿ËrÖ å6¸¦®ñ¶ÛíËjÜ­âhhê«íoÇ_kÙþuø[Úÿ!ŽÑ½™K8«ƒ—ήŸ[t"„K€äL0Ïä«€•¾³~ ¤îlJäþ°o瀴) ݸŽ7Ï ¹˜]ó'²š€ìÀœ›@Î5 ÷Àû%0÷e `3P8½®Ã7út”»hùô]ð»øªïI[èÌ6i³ßªy'¨Ö§ouÇO˜o™)?‚Êmå?nõ€ý endstream endobj 29 0 obj << /Filter /FlateDecode /Length 22522 /Length1 168840 >> stream H‰¼WIo\Ç®7ûpö•ŽÈ™)’g¸s,R%.¢$kId!R Ä"´±bÆ,%']r džo‰}ð!‡Ä0 £àKŒ\òÄHnFùJÕ¼¯ôJ/‰J” ðuõ«î®®®®¥‡"JÑC Ò…ó§ç6ï¯ýœ2“Î]¿»µ}uìóÏ)ðË:Qàáõ÷ïÕéïôW{ÂøìÖöí»8õç+DÎCÿáíw~zëËÇÿü19ëD}WïÜܺñÕýàË»ÀóÛw˜áüåÂ×DÁð÷è»÷|=¶ñ{¢P–œc¿}çÝë[ô·‘sþÿîîÖƒí·®+øÕ7<¿þ£­»7ï/jøà1ïYÛ~÷'÷XoÞúƒOe|û½›Ûzoá[rVñø5’³ý'¿¹-R‰Û2õsÛO|"ÊRŽÛå¹M²ÕˆÒ”á6J1nãÔ÷¬5ž>íÊLð ômÛ¡f£¾Þ©_»UïÐ[—cÕŽ³uåæZ«ã4Q`}dãÚf«à~pý`«äN Ì÷ã s' f„ûaF¹“3Æý¤0ãÜé³ûÂLp§f’û%a¦¸3fšûUaf¸“3ËýŒ0sÜÉ™ç~^˜…fÇ)ç[bÓÉ>nuJMRn:õÜH=¿1²qéòRµq¥Õéo’Ÿ5ЬoˆI:õ-–Yq¿n»_ƒÍzg`²Sç=ªÜ­L>zú ÷÷4ë´ä,µ:CÍF«3ÜüÂÙ³¾öE`ˆ›à07¡7á:7‘7ѽÜÄF¸‰rÓ·›Ä7ÉqnRܤ÷s“9ÀMv’›\“›|‹›Â7ÅinJ3Ü”g¹éŸãf`ž›Ê7ƒ‹ÜTÛë|‹5Vå Qå ¨²$ª,‹*‡D•âÊQ娨rLTYUŽ‹*'D•UQeMTYU6D•“¢Ê¦¨rJT9-ªœUÞUΊ*çD•ó¢ÊQå;¬ uãáÉÓ'n‡›§þ9ÿ-3nt»»˜cHvˆ€F2ãúaŒ—AKàÅF’‘À·Ð4#‹¾ÈœâX3{†°¾4ƒ1ý^€¼¤áë^iP»> Ý aŒÍƒ—Ârö†‘›À¼”9È_Ĺ刼)F1dæÅü`Ž˜{±›»ì…0y~cQÅyt½Ç>?xÿœ9탵úŸªõ¢IȶvJí‚îFnrÕw ¸Aß‹†öÁ6iŒ'17‹}§@Û;PÙ§†ý3;Ш¹ÿ˜¹oKÕw“ÐÃÒ¼±Q/jc×R¥ä.i€¼˜“÷©¨ÌwØOÆ'$ÖßcŒ3Ž2«/ ‹ GŒßÉˉQcŸ y¹0D^ «¿ /gd¤ _ó‡æIuF ÷(v–5ƒ³iÞ“}s÷ªc=öÄÉËSè¥~$/Ç1W}Ec"Œ}tžž#I^þÑý5æ3fžæ<]225G 8»Æ‡ÄÃ8¹uKd ëÿSàÍ£?92_ë`ÔôeLòð îùMF“qßËŒiÆûŒôÅ—–Ä'ð=…¹«à‹ïL€ÊØ ôÐÚšƒ’g£<~rV ó£ =θŒ9mÈ;̘Ç<¡â1ŒŸ…,Ù{?cR¨îE^N“}OâžuLì¸]ÓäåU‚ÎÝ{†|=ïiØChcË€è¾ãËflö[½al¥kJ¨yCŒ˜/çìÇO1ÖP;/"Ž7¤€žÎæGÍ[oQ3c Ïb {œÄ·Ì߀Ma— ük±…Ê­A«;A›!̉‘W¯4v5Æ,ßÖu]¯¾!/¯ê~JµþD ŸÌ+!®´Æh,fSaèêÐóo¶4hçÔœœ…¼ ¨Öw•ck òíNçhîÌÂÆicë4Î0tÌØ'GÞ["odøë¿æq=“¤‘§g×ûHC®Ò^õRïÓOí™l=óCïÝ}Øú*à5o3ƽW}òþ(ñF®ß–¹ÿ1¾å]UB<‰¿K›&÷Ý)±+¾ßzɾ]DÜöãL sæ,ì”çñè¨q£¹_ëá0ì!¹¬úÕ@ÇÀ߇¾­oàÕ1w?¾G_q}„¼¸Ó¢þa}Xã;fl5wjc̼+ØoÐF­—w@º /6ÊQÄ;Cò†äÄ”ï~ºÿå`WåÏáÎ_?`G•ÝiNucÆÆÏÖ#Gônc5òü[ßü/¢ö®5Îú}ÔÈeÌšýå5iγӹRäÓ›<_ürÓfo±Ç" ü¬¡|Íì9ô|N°z•}¾ ûØ8Ò7𨷠žÿ\þ¾ß°oŽÚ\ç þÍþ¾µv½gÏ×ÞÁ~òþ-‘›7"¯Ñ× ù¯4…:!ÿ%Z€Ô•iô³»Dì _/ìÆV¡×€×}/?cl#Ö+Œƒ&n»ß2|éo;ôÜÛ’v3îŸãŸï_ã[ÿZ¿wê÷‚oŽÚ‡¯“—»ì¼WåïG|}}oFn ‚žV_?ýo r5Ï…À{à¸õ[ÿW´ÖûsiÐwDК0ÀÚ«~©ïé@òvÒÌËê·IÉòÿé¹÷ã¾ ºï,Ç}³êÛo'¤qfÿÛ jlÞk­`ô%ãšgäý-y]Î&o£qPy;m:nŽ^ÅqßççÇ1.Ø‹³ìÅx òä ý3°›ü¬ƒÊ;IÞ[뎛•°—¼áä}(ïy+”þ}ÿùdÿS+:7ñ= ™ Žû¿@þ+Ìb¿¾Ø3þh?ú%¬­@çAøá&Ö˼EðeŸ“ðYý¨>üŒ'ò˜–0·;‡ûW™Ê>S°uöMÀÞ#8‹Ô²³wöÖ;Ú}Ç çôžo ²Îª¾7þ(öSŒâ-† -Cv²uÝŒo¿1œMÐÂ9X·sZX7:Lš¾è3îƒÈ¾Ï¸Å¸è¸ÿ/AÎο [°·úÆÿ³.ZpWuèX¯Œû”þ Æ‚œsh‡»Yä|ÜúE ¶®‚W…Œ dæA <Á ÇõÁ!ÜøÖ‡Žëw¿€œOñý±ãúìoð-{/3~ï ÿìõ‰9§È’8ÖÜ$o–ãÀ pº„pFëÇÀª9®ÿÍê‹G!gëf€&° è[0 ¨=ú0‰û0sÔÏ5¯• w vT ¤ Rvþ0xš'pŽÆ¥µq®6Î)±Ø‡¹5³^ö…mŒîk°õôj‚? ¹ÓŽçwÇó»’ãåÊ=Ž—«'Ï3ŽÇE@ýYí¯v­`½ìÛTÇ-ÆÛŽëCU  =¬í– & J=PÁÜü¿x/—;Ž+sðÌÜÛÝ÷ýšI#YŽ-bAÀ;CdáeÈ6›l²Î6ÿ’B磾>j'8^]]u꼟©·fÓïòÿCòùSôøjzj>Ò|¯å˜SÖ]Ú»ÅÜÇäý‡¼{¯ûfÏ&ŽÖ«¶üô[Í¿æ|Boñ¥õßæÆûÿáÍÏ­fÛMò²ŽÞr¿>ó­eÚ¿õjrî¥{òØcÊÙ|ø˜pÄyß¹}ó¿á¤«M¾Û%î}žm„ ·ÿæÿHØ7‰kL\ë|ßÎZL¼O[L sËï)ùÁf§|‡k='?¼’öû<§<$äj÷ßæ{Ûry†~ÿ—øÓ/Yw k+Ý`t{ÔÙ]ÊÕèÞËÖÙEþ½OÝb'×܇¤y/Ý[ã+ï£×Êmê‹xÅ'fÈ…½îÅëA´Î¢Óο¿[íWâmH:ƒlóœßßçêxó‡–§›ý8®Ñ}N¹’Æcü}àçuó)zsÎók~9ÃöÇ„g®Ýæ™íH|±g5<ÿJÙZýluöuÂ^òÿ}êðGÙû’ß?Eï…8cvy¿Ø'¿´³æSÌ=|¢ÇâF6F¶:GmRßO=±ÏÝY¸¯ÑýÏ}Ê>æþH<²ç½mr<²²v1Ï›ð8F÷£cž!˦ì‘ϱ ÎIzàŸEì=EwèVØ©ÐZ-Üm„üÆø‡…{¾Äï*zmYâÇ| ¸· ðuz3,Àù ñκ÷›»ò¿-t¬§Ê˺Ð^:ßÜ«b¿­ÞÝ댼4–3÷p«¢Kú¢!¿Öéÿu_}eˆ¹¾ˆ =ÃY—Sùb'z‹•έŸµÞ¬Ê¿Ï‰ë%û®DçNïLÃz¦ÖÙFkáùˆ'׳/éܼT½¹V;TŸ²—ì9 ~UþM»ÚØv©±eü_•;Ë .rÁRìT}WYè‘ÛÙý‚^Ö…–mrÎu¹³ÍüEŸW˜/Ÿ-ñÆuÚîïÊÿ’ŒÌYöË5êûP` ë;ïYÌu¾¢¯ _mÿ­ ÖÒ³ôè,úËSâ<æ{ò"5˜¾oæŸÏ Ô{hmµˆÇ—øÔû°½.¾®Wùÿ.>õ.ï¢×íç¤ošž•nÑç4ß·÷ ëĵž^d_ÖƒöÐÞéß½C}»/pøÖ˜çôFá¡ït¾¼6>¥ÎžSooŠ®Ìߢ÷X®]èé"yè!ÐüÓSŽ:㟾ýÂm8ûÃYûct¿lÿô‡¢[öøþ)æµbŒÞC"¯{Ý•p]¤oû½{r13Î^tà‹zI~¡÷Z:œ’ç!û1 ÏÒ×Fx\ߟ£Ï!ØÙáa“|ìÅ/z£OAwWÙ…ù“<}íAúÚE÷ëuÌíáüx­µà™a˜3ÈIžlóC¡\ÎSÁaë+/iƒ§¤wÍÿ¦ÇW:ÉuÍó«þ¯Âó’onÉó«<{“|]óû”çç´ÅE¶w\"Û¿‹¹o8Ùoÿ‘÷óû6ú ùSô‚/¼Ä|6²Þ¨ßÎCУƸ†»&ì³'>Vå¿&>׺§^]¤/ôóTød&%Ç¢×IïíØdŒ^ë¨ÅÑã£Á~=¶sSæsž¹µï«èqø’0SÒöëäËõú»<{[dy–]]GóØ«`8cOÜ ‹KôØ{L sjê½å9z=žÎÑýø,?æwSþ#Öý;^£ûþE²]t~й¯¢EÞæXh°'ÊýQxLã,Zôc»óªÀ¶û×1qì²/o¡{Kø[Ì{?ä?¶~¡­?jîeaU½Ö¤÷²Ù–UOöbïXèY_¶|£ú5Ó6.òívá?Û”·Û˜ûÕ—t‚ÚWˆõ*/u{\°ãÄò/ù™}?±-‰ëù*xü½ÛÈlßs¬XæäÝÄ<§ë¸—ìmÏeUÙÑ×V´–ôÃ9¹›µ]À _ð¯'«ÖÿAt_b.;ýoµ÷^pžÅ襘ÑÜ{»ß±ÏÂE¢û$}áëè} ûzÞ¾ot×ÖSù#Ø›öÏÏ­¼½jo=ëþ¶Knñ?¾jÛàgô†CÌgQÃ3_á»ô§òÛÙÏ7ºßè u•;÷¡Çè=2ùγ&0Äæ=gðvˆÞû;†ÁznÛê }=ÓA0Ìž¯¸[If|ʳ³2 …ŽçV÷‚ƒÞç{I÷³mï>p'|ž!‰ ðÃCÌeÏQÿ£à†¢?Þš7ë{/æù Z—˜ëjÒzpOÍc,ëȲ sr0¸ ï;ûÒ½æMÂÉþª7£îØ“<7 ŸQßQ÷ðÏۘϠ{ᆽécgxhÚ»v?ôQäYj!z™¢çkæ·kÌk~tŠ>OA£½WtKÞ!g“ÓS®Ñk¦sŠ÷¬CÊw’¬ØÓ3< §g6j1ÜþdÏ©ì‰kÛ›mu‡­ð1çÞ8ïR+n¿µ¡»£ö•'jtÕ[Õ¡õUõ\ù°žì·^ÈTë…u3Ų^¶ÂceOþ!·ú¯yß2ÂÓQpÛg;ãsù‡˜×Iò™ãØ~I.äËù¶àDç•ïAtÐSÕ•k½ë¹s)¾aÿ$<êŒØÙÇ»>F÷÷bà=ç?°;Ù†··è³=׳ðâ'‡|ó¨ÿ½ðºï?þVôΜQûôE¾ÿYøØßbîSÔMrWµù^°Ø×ù`+ltO¼Â õ }ŸÒ.5ŸñouŠ<زáys_?Jƒ¾Ô™c~á{÷ëÔ¾æþÓ²££š?Wœ“6‚«1líÊæû˜×ôç¼{Ž>ÔÙöœï<ëšëôU±ùþâs]TœðymëÉ}K{ó.qzŽÝæ¬3âªÁ¾Žž/ÜÓÓCx6²´ýSÌãÅütF¡–~óxs}­}8ó£gŽŠëÝGñPÞÔøs Ô¾ä=®<Ïí¿ðï=tÝ÷W[X'ž+ìçîÉÀµIý¢ç8pã7ì¿ËwÀ´Øþú?ëC®uÂ=ŠÞ.á¬Z»klAn¸¾‰îïoÓ†ðl>Ýà ëIøà½Ö6ô¾QòìtÏ“p^ôùÜ×Ó/1Ï®CÎýÕ§àv Þêܳ_ía=O¹pÔü¸)ø<;,õÉ«ò¯‘×í§îQè‘Vº_ż†µýC.l{Œ¹ ø6BçΓ®“Ñë1ŠÏÿ.>ùø›|ßòÆ­à>&çLòÝQÿÔqbÀý¹Ð}õÕoíØòý59á›ø<·WØ ½ù6zܬŽ8vtAïcÌýüP¾“öŽ‹%v?lyí£ž ðr“çºÚßWúÄ9°Ði´›­¢Ï¬ôb‘þŽy¿Šîs¶ÇÝŸÑó‹ãã=f“h¯tçûIïF­¤SŸÁ/½÷óx¥¶¸'cnEFú6ôg=Ы9O­Š|žC°ü9‡y¦@^÷€îg&Ña®Å¦î«Fѵ˜Ö”rš·¶î¢û8™É¦xÏm®»_²)¾ãü ^ûù\7íÇònÔ~-ÝS»˜ÃVIßùw§}ýŽÑó%ü1>Hf÷ذ#>ÆÞ3¥qX.ì€N¬SÿëôJøè.æþ7èÞDÛtêr_ë|s;¡_⃹ˆú®Z¡½OžjMµ­áExpÿÅÝ%æsÔ:á­Ãcù÷²|»S{0û¢u·)gèÆg¼?Kƒàª-ñ]–óÐAïWe¹‡aö<Ü®!{½%<ŸR¿È—îC]‡© ȺÕóü]Ìóòcobœ~§ö¸µ×vŸÏuá?î£\g—úBÏeîùk=ÞèŽu-/äB–“ýñzf­ÿf¼\–7Ž(3d“øÉîiÙ–dY+B;y§ðÎÿÿ9n„p—ű(Ô#3+Ÿ7­GìøRklcçKÛÇX© ÚÖÑ^4ÀìÆ–3±¨ëôIô퟽h³¿×}xR¯ñ3ǘsª{ÇBÞñyâÂ˜Š»ÎÕ`´/µä4bé»Zr<‘[#;1f9ݯb=mëÞ/uÌpݯ‚#À ä^÷Óÿæc¼….†y­-r9½µâ0ŸÍäšxoôêÚÇ[;ÍqÇ~eúĸezÛoóÿ×ñOéË5ú4ëíë,ßuoó:ukwésš¿Îÿ?|Œ÷úÃ7Àf÷y ó¹{-~„-|î^k|=ñÿ¢õ«æÈDn¿×Rk¨Mw½×ò¾ÍçÌ÷ ^û^wïµ–Á;˜ƒk¯¢“ïÄ7Fñ¤?t=dà~8ˆ?ï„g¯{Œ[Ђôzî:Ë>q5ÖZŸ£Þߣh޵øÓI@æŸkñäFæÓ¬°ÏµÆªä›)^Þk©×ÓÙm-õØu˜å¿iÏõïVK#¯œkñÇs­ó¤ûH0ø³Ïý"43rÆyÝ5‡8pØ×:“·ÑçIô]§ÜWdžß7ÖüG]5Æ5ïsÐÅÿ4~±žé]S§ÖÝ Ž‰åKÜ3Ö4Fð¾q«k"û—ÿ£Ÿ½ÖÐo1†3Î4½goÎ5ãY×WlbŒ¶•Œ¶“}âXºÍ7&γÿ{lB†ô5듸´ïïëQ–¾±ßC¬;&OºŸ6³/¢9Ô‚cÇY-Û3©µ_}û»Ða+9þì››ù^ö±œµñc¬ÄŒÆ·öý–,ƒßË›óü û22æZþÎû^tï$Æã¾÷9þ÷µö¯×'oå=­ž¥ËŠlƒNƵcÁ¾vžï’~ï!ŸíÌÚ'ý;v9{¯ÌøÇ¦–x¶-÷µŽküÕ9t_KïãxdÏyƱ…]yÿK=êÐwÒ_˜û\ÊövßešÆ´þG°ÿ¡q;Þ;kmÐÚ1î¶dË·»ç³­.õ¨›ëLÏ{Çøbós­uq ^ø›iõ(›eä tkØÙ}þëÌÁ‹ƒøpçÜàß×£\‡ }¬õ;m3bÊ6%Üo /½ãE4¹;ÿ^ë}ð>в:ï·žµvmx]ãÞ¨}tòáAƒ³Ö“ó°÷Ø';öýNrgµŽ)Ç ù ý ÒyµøìU÷y“å½JŸÈOøX'ðékmG㟮ÖyÒ6äíȬ)¾{¨µ,È;ÖÚ>Ö‹}ýZK½kñQ° :…Ÿuæ8to“ºH?±ÏÕö¥^{®7®ÿТV¡ômæwé—ó}­ýÒvKûåþ±ß™oÉ7µ|sÔ::‚Ÿó ±i,’r%Zò´Þh8’»û¸Pëm°Ü¾cþé³®ÖþsˆõÖ[^¤{ë˸ê™^°Cæîñvæ-»yÞÅ7ãÒ}á4¾…{½gý¼ˆÆ>øž‚¿}³•WœL{N5¼‰­ÉÔϱ–ÚÎù ¸„ºæ8cÍùŽœîû÷à>í:Šc¬ó½‰g o]%ÿ-h‚÷РÞýûYÊët.9ˆgÜ\EÏØ‡|ïzŠ c-=é›dmaï¾ñ“ùÆ2ÈI/ÒiϺp3žz¨%6&ÿ~«¥n{ÜÀ]p%±@¼c¬ûÈIüÒcZõ)cãºO,·|ý¨5Û{¿I~êyå{¯µôy¯µ>œ/œë¾Ô’{κÕùäcY˜ßu‡w^DcüFæ6ÖRfó<ü ÚY¬«ÖøÒ8COúLÖ=ôJ?bß=Ç?ú`nrÀf¦á»›ùÜN|^jÁ0ÐØÕç˜þv¦Ÿç¡Ã;ö¢VÞHÓÙ…lí“^4¶3=ä³¼­±/ódt ðü¬·ùÝžoê'ò†^{|Á»ÆñútþÓ,Ç]zà|Úƒ»Ÿt–~ÙÝüû÷Z×:×N#ûÕN´§¯ó:xĽk)=vö}ÓÜÇ¿e!F]mÓϲ]Ò‡6y CðèôŸ›èOØõûúç¾Õ’gOâ…|Üc›Ÿñú^ý‚ùgŸˆN·Žûl§|bÍë¬ù y—¼³‹/{b-ßê¾'óIÞã»}²ß’ãoÞã=pÅ}¶éô}ŸçôFÓþ8Ï©ÓüU÷.óÿ«ÞFÍ¢¦ŒóúµÖxçK­1uf7Ó»Öâ?Ès° ?;kœô=jÝ˜ŠºNï‚nNâE/Ãp¯À9baˆÿC­e2¿Qrea¬ä÷ ò"ÓI4ü¾sÐDÆŽc­õtÚø+ØáûÆ¥'Ñkg/:Ÿ}¹Z~×QgÐ/¶f=]ƒßE´™á|Ïðsú€õj ÏŒÆ}äéDœf¼ÏýN¶…6ÿÖ}ö‡öSì£Ï^|Ì›9¹‰±“îgÞîkmg÷ƈƑæéÇ|‹§±‰w°v¿¾ëø!O“×7ñ6ö‡yo#ú{ý3ïtn3ßÝè>6eÿP Ž¥N‚³‘o/ºèf]¡· >ØG÷õèüÑñ˜ùaÐ}æ‡Øs]…ß]gÀføæ$ß{­ýÍþyh¬ç™´µ¿¬»þ'ÞÛìÛ©¾§Z¿³¯µžÌ¯^)Cî·ôžzMZ-ìÏ幬™–k¯ÿ¾Á—ówÍ—ñ1â)sĵ¾ýnãyëÁ½*¸Ï=¸ð^>â‘÷Ó‡œ?wq}9wCƒ¼ì5ûíyž¿I^è;wÃ7ÛŸ‡Òwvµä¥}-µ:s§k 6ëõ¬u26ŸÎÝ4wŸg?÷°O¢ûÌé¶…ã=ók“ÿ>ïjÁi—Zò!xë:¯qg¬µÍÀÈt«%ù¬Œ\çÀä@x‚ð¯Q¼Ðõ¼Úéž}Ñ8ɵŒ`\æxõ¥'C_ö­cœ'–·:EÆ_Öñärœ§/œD÷^ NCŽV‡ÿÛO÷¹c„:˜zgÎ÷¬3™£×Ó÷UçOOî8f:‡ÝçÆåÎÍØÿ¯µø~û«ìeÜc\Š‘Ÿ=ôs›÷.Ò~þËÇø¡Öx4sÑX¾—ù¾³¾¿oÌÉKƆèÄ”ž€Ü…]‚ï :¹n±üÝs޳LîÿEzÚÇ]ódïÐXË÷>«Û®7Çà…?Nó«lœXŽXûãeöjËQÅá÷î½{O½Çsî¹I QãtÀ¨$ÑGA ø øâ“ ‚>û‰£Ýœú读Îñ>,ª»ªÖPk^Ž«¬)w{í¹^gO²)sÝ­Ê­MR·¾»Žkoþ°<öš¯êÞøÞOêÞøfòÊ¥ÊI6O÷†‰þˆC¼sÔsæ¥ÎOe>orÆ;\ãÈyÇ2åÔìgÓ:Ëž÷¹~1{ãV?±öܬµ?êã=Ù‚š°­:'GÝÕ•Zžx÷I6:•©þÊ”“Áïßëî.h^į×ìw.“ØÔ;ì}bçØ K®2íc™¿wjýÈE8WÑ÷;¡Ažßí‹pð{ÞBÞwmÝëß+ºäÔ ôs¾œ'žû-ëÆqyÔÕ}™Ûy|Áa層‡÷ˆyør϶¥."çöû’û¼ôÛ;Á÷ ~ÖÉU|,—óú^|œƒl7t”}6ïpßw(óºâžÅ>Ê[¬CëÒvr,уñjõp-î8Wðfznç1î˜<Ý×’Ñc)yQ^ûð wÇv©ƒS™û.rìtnºøsØQ4ðÌ3¼‘ÚÜ Óž±lCÇæ®C? ïV|Xhð.¯™OˬÞ~>Øž¼áÑ1æ~Ûyzž™2çk‘Óó&sÈUo݉fÎà":ÀÏÑk/›r_αögî¸OÖÎý'­ØÊ3¨mt,Ó¬€¯·aÏèÕõYÜ«¦ŸZGø-ïà.çžcsnB¦ì<·ñv닳cƒ®ëCæ»ôlaÿÏl¼³Ò>Å»8¿tö:èŒô_”y¿èþÍ}©W÷þ}ì9'º®ÿ“=£{bâç¾AS¦üÙ—¹-£m†KŽç”Õôl{î§%¾ç6û‹kMê™»2×OÎæåp<­ƒ½î›¯ßóÕ>èãŸÛàiº¹ŸqsоïãÞE4_Ûøvíå½áDœ£¾œ=›·5·&=øZOûjW÷Më2ÿ]¹}§g¼Ö;ø&·R#6e^—-wÖ ÷ŠäçMïY÷¶7yš7àk]ã®çGbÿ»ÒíNLa›´ýŸß…ì‹JQ¡¥SûÌxg)¹r¦…ߢÌíâ†X] õÜ롞ágøŠ÷»ú݉ΘÇÉû଴· ì‡í^ênÖtb™_ÖÕ4–²!~‹ŽœW:ÁJºZI×Ô‹½þñ‰•p×A/y'¯¥ð_ÆÙNßèu]æz¤¾»†;Ÿ£ãÌgÞóÜë8Á?ñ—‹dÉz‚]õOÎ<нÏ&ô8Ò½ÓYçÄȾÌm¶®z{QÁoqíœY#ÏÝ«»ô—ôÜ_z&õ|ÇÝ­Î=_øÜròVÿÛ¾¦e¹ç)¯å¶ox¾ðüs(í÷ú=)sêeSnßlHû´ô‘½‚kß.ðzñN^æÿºÌ;¦ëù)é$Žõïî>Óµ}[Ç» ¿)s[¤YóÖåV>óEoîG[:4Ïm¹µ•mêý”Od_—ö¶¾Ý«ÚŸ¬û@îÙŸ2¶Òæ¾G­êü³6çì辸5K éÁÓsíHÏu™zzúÏHÔ‰“îŽwÞÕ½¯—¹S/vñïóœ•óŽa¬WÉpW¦™õ,ž—z‡zAëü9â½W¦\²Ñ]¥wŽûy÷ò¹>æ}ê.<ƽÉüºL=(z9 ×==Èé Ý!—s=½·k12Ͻ qxÑÛZóÈVº²?Û‡œ;¼—wò ù—qv½ô—ô¿•µÍyt§;®Kö+Çú¾ÌëLÖËìS]»ì·­zfš‡þS|ûÔ¹ñ“÷Q¸†Ä¥Î:Çeý!#¿sä£/Þ¬Yì]…GÎvïå~ý¨wô»ÆýCœo«}æµCÐÛ~_n{oËpŒ»Ùïä>Ï\—½ZòIÝa÷¬ îe³W4=ÇŒc$ßÝŠtIÞñÌ’=cÆ_îƒçÚáqoi[QßíôÎùÙ:^Zþô•>–~^…MF½+S·nÝßweÞ'n*ÞB{#îI8Ö£k«2ù <–xGÖ¤¾Ìs/]™ûúà]îe–õü…ä[‹žý‚^Ø~ng-£ß¦î+tÒ•)¯ÎC9¦·ât÷ľßÃÛ ZI¿EÛk椔uWneoÕŸüwî° œ¿mÿçýeÕ¹s±kÀªÜöƒ¦³¯w:ýg¿’ÐÅÿ*öüïÉs÷}Ô«>î¶h<'_ Z4V±·Oõ?íåY'ÝñŸz²Ìû ±,m¹â·|âžû*ògòÎÎónú=EÖ‹çè¥-[ëÿ“ÇvZ”É¿Ÿ³£g…Í4[w÷qº”²>õ6{®DïŽÃ®´eÜŠ÷¸®Ê|fj½¯Ó¹ëÑsºÝ”¶_[®]œçó\ ù]-½·d‚vß~÷xn‚9§å›–Ár­bMÝÙ~}¹µ—Ï3ö×mþíg^Ó“qñ Ë¿næ'û¥çÖmÜ]–[»íb¿‹oדUœµäN¾èd,Ž5À=þëòØG0ömã¼2úÆCyœIêÞ½ÎFx¿þ_+«é\ëú ïÖ:Ü» ÿÏu…8gÑÿ¬ïÖÞ%øÜé žÆ½ ¼Q—¿oððýûªã«è=4îÞWÝÃ<Ô="+úkÉy¯ûWÑ;éÌ:³¼ôí)CK?W½-÷ôNdÞ }ã{÷ºç\H´7þ¿÷2¶ùN?=ÇŸóè:À2îw×G¼›ö¡A3ûÒ½öú°;÷úú~lÀ½^t‰^ûèú(œNàÚî™Æ3‹ca-¾Ò½ó¢Wç[ç÷}cßµ¦­sê":ÂfðæÝ}™û#µÚg½xd=ÄNÇ2·i>%gë½¾ãœk÷Ü_ºçóÿeª îl b`-îí£Ü?gZbŒ;ä+;7â3£]<»97uÂuîÛëÞFgî:}Û_Ý"ƒß‚ŒKÑ÷LºŽkC'\÷(ìuÕn¼k<-û²ÌåöYÖ£ÄC—]¹•?sÈ"ä ³ò?u9m•µóeè…\”ušäSð|YÏ» Ç¿ýp_æ²[o+ñIþèë.Ο«ÍÖ%12Æù†ý“ÎG¸”iÞÀŽ™ÈßÌ6Ùÿž+E™÷uônà^u~”Lî÷¨Ù·‘§Ø#î\?3×_‚¶ã-ks=ƒsoqŠÜ|/ËTO­GËŽŽs¥÷¸ŠÞªÌõ mf3èÑcc«…ðxÛûåq†ÄNî™ð³ìœ±#°ÿc™ò 6ãmGÙl÷ˆùñîeòêáQoÏ}³ýß3–óÔA8}ÜwÝ8WÝ»fÞ2xÖAgîçLc%ºÔLüŸ^t+:ñ ï±À#ç ÇcWæ¾ ìªídKbž‡œ*xÏ} osíz[ÀGÜ <Žm÷9oÔ[Û‚¸ÆOÈe¼ÕñpОñlÛ«=ôŽOÎü뿳¡<ƃõ±­ò\Ê#G?–">Bb#G(È!|$çÔ=·ûÑÌp¤wTw©[·ªnݺõê„ _R2Cñ&ÄË~JòòËh|‚æ2’‘O ЦvB O“ö)ˆ·Fë›5Ö&}Z¥CAzr¯¼ü7JqÈ/´¿Kº7iOÒ¢éÔÆéeÝCù) ŽBŸÈïí±qÛ¶§§Þ¶!U>«“<꘳6ùÝgÓÁz´KÀ)Øt¼}à; zØ]Î@ÏÙ¹|ÇÐÞƒñ  ?yô$|Ô z²9w >½ÿõBÇ# !cÖnÅ^ËÐ_ {hûj¬y s?4seʹ v… úLÿï_ѯ³öy³£lƒOÉO,‡î°îE¬Ûb2ã°%±Ú5ÁÐ&ú3¡ÃLÌ­ÆXÅ÷!ü ¶C'êÚew©ÇΨ„¹æ'ÚBÿÐÚ%;_Þ»QÁ,è9Ë|:ó;«óyã9›ãší°Óc½üÞJÏâ ÎÂcdtߨ>+_—°g˜C¬}r¢ }{qf{ѦßûCÉüž» ±ßBèÍý_Ýn¾sçPì?4­;RÏ‚çEJ[¹Ÿ§´ûÇ }&77 eŒ‡Œ³±ô âün”þ`L DÏØ¤Ïâv÷×ã_ƒ­_³p~˜š™³A%З±Žwä5Äï c•à}™‡$;BºkH— ‚EØëŒÝûBD‡¢|?‘ïJòu”î4ÊøJØä=p4ct-æz;܀”w–÷†ôÛ¢/šNÅ~uŠÒå>ý[cwŽ1Æóõ÷žw¯š2v>T¼û³/é,7o–svm—6™ìtpÂúYCúë /Ѽ‰5«@n6¬c~K݇óÍÆ¡x©pvq´ÃàëÁä³äTpþ8®5[m¿0ØönãwØd4dy€{ÖÞ€Þ§mÿ8Αg7ýVBî.Ë µà+@f²SÁŒíAû0Æ7´g‡Ñ¬ù„túÛÀ·{m4[3¦ß÷ ûm¬ýÚ'"kúÌ7 “ß'?±Ïs ¾)Ú }çY.ËãŽÖB^<#<®7¤Ûb„¹¤Æú¤<÷µFË£ì#Ç«vað¬êžnõ»TÃlPÁö¸HÅþ#â§ñÕDš›b9ˆ1¶v½½Þ±{ZŸ†ª&Kþ,Õrª]檦™®±GT‹Mé$žæŸ“,îý0‘w,Á½à»Ðè‡V£.@»ÆÞÏ#Я±:÷ƒùz¯½#Œó<ò\sÅà=ŒŸ°š}rÄÞnù£;Rïu Ô}¬æ»"sóäïª ½¯üšf½WÀ ⟦Z¥Su ë—`I¤-Ú-,’O¿YãçækŒµâˆÈÜóÒÇ×Ä3´ÇõÉÿ”ÕV«à›5ðɋǂùíÄÕ!øôåÈĸ{?~^ÞÿãV›Äqgønò¾å,·l²8ÏÁÇu qä*ö³ÈAyÔWiÌónÔ€?´»îîwÂî–£IФ­­Ì»ý*Ô½I{ÑíïCæZè¹ye bàП*GCݸ pw1 }Yƒ¥ƒï@ÇcX·Y9f·éÀú)‰œÄº«ˆ>ã¥hºœ´üŒßéÀ¼ý«ùÆ'Ë”¹ï=ÝûÀIì³Ãd¸7ç¤jYÚ¹ká]o ¾e1éþ3\ÞO›Î¤^ÿ•ˆÓ•èw2¢Y Ôª–Ñiuxof^¼âÉÜ×ú3ªõˆ}滜—ûÌVÆ£ÃLóÁ!ÓçCl2~2²?¥5)‹…É{ÿ.âò¨Åfž¸â´²²ºq»•·2üÂâ©Yà¾äK`¯ä…æç ûû°gôXŽEð7NûÁ÷ ÐmºWïÚ¨A½Ã}‰áÆQ/°ïÿA“ÐTäÿ!euƱ×Jåâ‘@“ÞÆkp¾GÊù|c2ʹÌû|ûÚõ– ‰¹·ø)åö¡Z;]4,•Ü¥ö†­2?eägOΧI»þ ãKŠÆÅëÇ]]½ªk—¯Ú´6.ÿ~Mˆú±´—WM©?ðhäŒX;MŒØÓŸ]u‘±è|úP-7Ù›þxLàx}„Æ€@4VegV4ª£—ßR Ü'¡¸ñ4%ÿvj¬Ú®êv"ÒOVñxŸ{¾xwø¿jmt}”/j_çmü'ì)cQ Œ­ðƒÿ@üâ¿ÿ& |/&«]H ú „{ñUâàË8ÃàK¾·€uz3ˆÅ@·j£Zß'_¤½Žk­Öé«È¹Û¼xº=O´íõ‰®©Zÿ@ûýµBóOÉêÉnݽn!ˆà~Çï·wTj]GÈ¿þ<ƒÛh©jíý÷Y§%Êpã§bîý©ü*oýí¹ôIÌ•:¢]ðoB+Ш7€È ­†×Ý?i„¯ ø÷Æñ¿îþ ÁÓ Têƒí¶G³ôc]ÄZ¢µŸw*ú^Í 6‚n´¶¯ BwhmhuáÍo)çÖÕÌë´µÑxQÖNOÇ\ŽäX[ÌÕÝ=À\Í£dË(Í×Ikó…j/”ßø×.Ê:‰õÖ“1—=mÔ^¬áX²~a­Ð"  íjÏ‚û—xFr©óÃê‘ÌŽ˜û/à¿Â£Ú¯Yý‘Ú³AãÃD©Ý¬µmÒy°âði­'ßcç> ôÿ—Æ¿ÿÓA¯¨Æ)ÿŸa„—í—ø¿soXA¾¬Ó™Ñߣe ß²9‘½›äoFIßqÒs†ôþŠÆÆIÖs^_É›ªñ1ÚÏcŒÎ1ŠáÚ"Ùí’í×M©Úoœl#&ÉŽ‘Z7V<“´nªèhab¤M}ÆW²7/K€bîŸoªlœ¦ó¢/µ·ÿç»E£Îª]:¶h¬EçÉö`Í# Ãú9›öµél|\4Ë×C46D2Ú$³Hª|ÛF ÿ„xxnC•—šW¯”W›Tslxàþ¸oÚÃÔßãÛoëàÿ¼7#{AÏaìwÀÕ ãM¹ûØ|Œù«À´ÿŒ×w {ük?."_^.C 7Q×Þ*ç¹|p :Þ®Aq9ú*Àý?Çü¿M~Ápò®W!ãºÙN=²¢Ã< ¯ÞÃï«ÜW ÿßÍ×uЫ(bïìÊ›¯?F]~ ¹á7h_6¿´ÂGÃÑæ|-æ h×Kf‹Ùôèwþºd¹¯Ípï⯱öXó)æ~‰wóÖþraKpcŸ`íŸ@ÿû/^nB¯ÿ€Ò×ÚXþ-@ïœâ¤`2?µ3ª6øÚ· ÿ³— >ƒ ®?öe« þ=yg+ç`÷ùÌôÏÙ~çÊa­õº"Ü€<îõùÿh¯¶Ø¨®+zçyçá™±ÇØ`HÁIx”ðp)`ÂÃÁBRÔ´…&(’“Äy˜gx'<íÜ´‘ÊW“¨ªøˆ”æ³ý®Ô~VªÔ~¥jÒµöYwæ2±HDºKûœ{öÙgŸ}öÞgØŽàÙ•1þ?à3Ó3‡yÔ/çýÅôÉ{×ÑÿðgóAžK½÷Wøóß¼IX¯:MÔf1·ÿi‡±˜“ó¾Äžÿ|…µþƒ³ú'Ú}xW~e²ZÆæÝjú¬â«!R½7 æ9潌@æEÚ¤^í ê7HNƒú’•‘¬6µíܼ—Ç=€hÄÕÂäéOÏÂ>f+>çíŠù€æ¼[s ý[ˆ‹[ð]×o¬A2æÊAíZ‡ýïS¼3¿„-oã>ý¸y‚¬/Ð^ »¦ôÕëðááßvöðŽ7øü·±ÎUÈâØ§^ç…ŸGàWQ€±03âê0ËOÏê¿fïC¬;ÙïCÞΗtøÏaÍkÛ þίÿë]‚üNôÿ ÞkÀ xApÎσ~9[°>ÇÙžbÞà]èpÐÖgŽìµzõa˜ Ô©ýˆw ô(ð*b°ôuÐÃÀQà°¶`9Œ±«@?0„õ.ƒÞÄÿ÷_£}¸&Y%à¢g½_g€÷€z`GŽQÎ9àcìýÉ<Œ=S¯+Z—ûÞü8|¤58v8 œ߀¿9í,Ú;YØ/é-6g½Ç:€5 }o¶·…•ÚÝWííÃîixOãiÀ¯Ôõóí~ (kkÚf‚ú9ÉkP]ž7~7'£uRØO9"¿‹aÏ ØO6h0ýOãü]†qþË ó$ø.£}ÿésüÿ{È» Ò!»· سoc7koàãEÐ~ÈØ‚¹°Öôwa?Üû.ÌycïšÎuºÞâ3e÷iôYøõßÑÏYûz{ðÈOl…î=˜÷¬ù7eư—8þ%ÑŽz¯Aÿ%è/K0¶ ÿª¶g-ÊóK˜®‹,ö×ãÑjÑmf'îˇþ¾µËv~Œ§ÉÞRè¹Ôl:ã;«ùfó<þ×ÙXÙÞ@é öÉî#¡ ð,úu¶@F7ð2ÀöDzuÙrý€^K­= 9ap'qf'ѦÝGB9ôž c-Ö[ ½¹þs ‡Ìvîj€õ§€¦BïÄ‚Î%jçEʽr½€rßï–Ü[sTJ„ æ¸ã ýòó»QÚ£ÇÞ#ÓaËÙ´Y 4Š3Jx/a¯?6pvXÉÜ™Ë@éeИÇy >Å8¡¯Œ—ðAÒeˆÒM˜CºÅ¨çmÀZÃ÷…EÙÌ·Üܧ³¥}Ãô¨QúWÜbqàhÚèŒ ØþêF¥ŒYÆ éÏEŸ5Š#ê¦G+}Ú7j1GãùqÏØ«¥‡¬þˆÝqöeýæ Ëc[ç å„^“BNf?kà›r/ôÝëÞŒàÍx;@/ƒ¾e2Ò˜³œöնLJ¼8ƒÇÛÓû êž«+…pöÔœ¶ž»¤¿#¿C¯Ñ<†ä®Yox zß´õc8GžIÌôÛ¹Ç,'dÀW€ÌdóÞñá)ïþ÷ÜÏa£Y³ i/ú¼[÷c­ý¶×´é÷*d¿¹¿@ûJhNÉl7ù%Ù‰}žñSÑè»ÂrY1š<ß[#,ÖÒm>Â\µ>)Ï}QÏò(ûÈñªãVëÖ!Ýê/Џ÷fЩ6ß|‹.U¶xWè?릇E96Çr}Œ5 Ðë‹Ó(lÊzs¡ätJæ2Õx¬é–?O‡ä-æ‰ožÕÇLÇŸ’,®Í7ã RÄXœkÁv¾ÑëVgv¡µûó"ôã[nâƒùú¤Ý#ôó<ò\ cEÔ>ΪAòƒývˤ -¨ûT/ ­½i«„lÌiŠTß`Šžjîqê“õÀ&àq`5ó¸h·°A6}<4'[©«€I¡±§¥±@:r.õÉ¿>ÌØÈ{»a“óÇ‚ÙíøÕyØô¼åÈ(|ÜÝGÀËø´Ú$†˜á½Éx«³ÜÒk~^ç@cÈU¾Õlý˜w óz-6¢à÷-Ö]|Ç-¶M€&lnuÜ­W¥îN:‰þÛhÿ2÷@Ï=È+»á/€~ qu|/àb1}Yƒ¥P³á»9Œ×#g¹sÜt`ý”@NbÝUDŸþR4]†,?ùVw:0o¿nµ#ïøD…2÷SÜŸ†°Îa“áîœ!» ¶Ï˜ÐåfŸ¸Í£o™‹ÑP™K;3ÇÔÙ*…\çîÜÓª5È»ìƒ^ÇÍ6«?Af@K–s³#ÐŒÕWŽF*4Чú‘ÝÉî.ª¥ÁÝÔgõ›W¡›NàQ`xhê]¡þ ôá®Ø`{Jª&trÊ6Ö4…jîfëoE{·é™P˜gwPA±;ý†×ðÑç’ŠÛ±æÏëô~(Ù%¡{“±>Îû™ùdÆj]—÷S¦3i ÿvøévô» iÑ,2jûtXžÅ™o£xÒ÷5XµqÚlW§xsõrÉöJ î0ÓßlpÞtçùGà›ôŸ´öŸÔœ¤ùÂQÈdÜŸ‚_^2ßôÀ“ŸÖCVVq³8¨Þ•q¼ éOM×%_kÅ!Ï7;_ƒîW±ŸcÐct¸äÁ7Ýt¸œßó W§,¢¨W"ˆ—â0†zý¸Þn‰Qh2ô~HZÝ€ÿXk»rq0F÷ý‰58ï£Få|Þ1iå\æ}Þ}­ºË&DÜ]¼Z¹ý!Í](Zl–ÜÍv‡í0;¥egçOΦ ýwýmÆ—‰7øïêꕱZš@>«·{Á½Abz4VòHÉò¡_SÛ¸~ί«¢Ÿvpc*ÿ“Ÿ«ÊhBûð‘?sMÌ£ EåÓ¬x‚=û^xÛ nð~K¶ßê¿3F3FÏØ]ߎ=ò,Ys,V› ÍÑŸÈ»ÛÞ}v&3Õ&O»÷¡{áÿTå!_HŠ'myk¾å†º`œyhÖùN’Ïql‰òÈV­7UèÐÎû½…çú„Î'ª|GcT?LA{eI—@'úp£Ùµú.ÿЧö²²c Ó‰g”yÓB6v¹ý€Ù¨MûˆÉf­²U‹æÆdßo£qÑà_*WK©?ðXèŒX;Ííg¤}åBÿÂã©{@­Ü|hmÚcÀÿõ!<ÑHÍ>³¢aùÍ5¾Àuâò›€&eßý«ÝWm;ê'jx›|±¾aÿš¹áùa¾ðþ:îà¿bo¤|„DÙÛз4ü ¾øâ[o„Yï‹ï«]H}ú†{±Uüà»8ÃÑ”|o{ugnÕF™ O¾P{/çZ­SªÊ¹Û¸xºžp;Ð'<§fþíÔ 5<Î>e«'»{Ý‚Âýþ¿;ÜÚa=juÝ‚'ûçéÝAË5sï¿Ï:-^û#âîï6åï¼W½ëïÌ¥«0FTëˆV!¸Æºˆ:aœá÷& ñ„à¾qü¯¸w!xš€j}pÈÖh’~¬‹XKŒáž ßWÞ~ÐýÖjßþ;Œ6×·ºðÛÆû*y†u5ó:÷ÆÚhº(k§'#.Gò_KÄÕÝëå'&k/“5ž“<ÖækÕ^+»ñ×*Ê:‰õÖªˆËÇmÔZ¬áX²~a­Ð,Œ¥íjϳ‚{K¬‘\ê©ùä[ ÿ\§Kï¿ÞV| ¦¼Qý§<¼?ý/ÛÏñ½qwXA¶ÌéÌhï)Ú ï²ÎÐÚcdïàŒ‘¾Ó¤ç¥÷Ãú7M²ž ô•¼¹úß®õ´ëآ͒Ý*ÙÁ¼95ëMÓÞˆYÚG›æMÏ,Í›+:E˜jSŸé5 ìýÀN`ðLĽùæjót^´EãÿÙ¯²Ø¨®3|îØ¾÷Î̽wöWìñ†0^f 0;f+"dÚª4u“ÚRJi¢ª MH¤6$¡MH€6”¦…R5`Ó:!Q9$J$·âñاJ•Ú¾´ªú~ÿï0×i¤Vªò[ßýÿ³ýçßÎ?çpoÿÏßÅ RŒÕê˜e_–ñ¾ŽãuD*±³ñ±"ľfÈ»íyÜ;ç1ÿêãäx˜Á~âcÏÇSà_ÅúëÀ[¾œ˜šUwaÎ(ú"ˆ‹ ¾ì“ Œ•øûô<øÎ"毾€¾9î£ýWöqœþû~;‰xÍûz8hG 3êϽ^èг¾]|’öý7ççLZ=½æà»yÚ> ™o@Þ5È} rD¿?aýß±æØûÏ࿃wå¼?/ÈÙü ;}”çK~gôï¦Ç:'u/BÈ©‹ò'_Ïv‚rl§(+BY-äe,¦¾Œs| 5Êwa™Sd-èƒËx>圷ñÌkêªKs íKðÑ%ø¤ÜN-B2†¬AmÜGÚyäZ•zG凞zôEà§÷[?Çrj~= ŸÎAÖYÄá/è“þw1þ"rî]èñ&濎}žƒ,{I…Ô¿€ó0ëè9ÿ,ôå{˜_Ÿ åßÿ²ê‡Ø÷d? y§O¡[1_rô äŽbþè{ÿTÏBþ(ÚÅÜ3ÀiÌ= z 9sè g7ö—±‡|›ªÔQàÛÐá»þþR#ƒú÷Ü£@;à_ª}8ˆ»â7@}x8€/äù3Œ=~Âúð<úŸ΃ÿp†²~ <ãGÕÏÇGS†eLäHNŸƒíߢ̇a³èõcî+vòó> »¢êGÜCÆŽOaÍ/0ÿ8êáàŸñý…ÿLµÚÏw¹ïÉ=@î(Š¿_#÷åû˽ÌåÛoF£ò†\ =þAóþÛõ—€_ñ 9g”ï!ò.&9{kU+Ñ}¯•>¹«­æÜ)î=Á¶øUîIYê`“J Ñ÷ZK҆沜'1aŸðMÔ_b”1*wÒ$i‚ñ•}¬€ÍRƒº2e]÷é <‘¡ï¹iêÛÌv-mIt–zÔ˜ïQv.`wåèw‚M]‚ï‡N®O°-úöÖi{KÆÂ:ÝàOì ÄXr§&@%æî>Î8éü‡þÈsn’>’ø­f[ûTçSý$¹°Î(¿ý¶ÑV‰«¼ƒº©·®_0ÊçRjßJ£R‹šc]ÏtK•:ªë‰¶íNuBdÞC}îb{Í"HÿW€/åº"û SÿΙd,$_>Ë5#ŒÅÎïâÜ.Žõs~‘ºJmZ¬0*5N ¹(g|·Q>'“ôÏ(©ÄUÎÙ8}õ £œ{‡é“ô¥^s?ù)®£ŽÈOÕËÿT/Å–R‰—Üֱݠmı•Ðgjå"L­„®ÝD;±œxHNw•šW:+=_÷÷z|)ñI£òû£ý¿hg{9ùÚÒB:F{ÆW]»´ï´ouì–Ñ_íôëRÚ)sw‘~Þ(××5e#eKm׿KmäKôǧŸêè‡¤Žª-WÔèÎ)|;§®ïVÇê}jÛS?­ŽîÙrÅP»¦¦iãñ=—‡‡TÏåø,_†Oo>K»ðéhǧЊϒf|TÏ+ªI5ª†ñÂø§7¾¢ZÔÕL¾MT+ùNÕ¡ÚÉwãÝÛE¾Oõªòýj¹ZF~P ¨ä‹jX ùüå۱붭ølÞ„ÏÝølÃgý(>k×à³z>#%Ql¥Q% ¹ ÏÐUäשµj ù j½%?®6ª1ò“ên5A~‹Ú¬6‘ÿ˜Ú¦¶’ß©v¨í>gïÇÿiüW!üÙý¥ý¥’ÁR»ÔƒjúÝé&ÙØP¬»4˜)Xî‹« _W3*Õø³JC¥âà@.Ûh¤-³ÐÚÙ1\´L4rÙÁRq1ÔÙQ§½LÆK—¿}¶ëÙáˆíºvd_oÚóÒ½é!=Ûm·-Wðl!m®-:Õ«j¨>£"*#»ÍV‡jB!«[ÍÖX¦ŠvE¹áÂ0ö3œ\SسÏE_8êØXëBý¯ªiÕªíIÆSñÑ­5Î@aÿ_DKøe[-3“ˆ»É¬ëƼ˜m[5[>Šåã Û ÛfôPsÜuÝTm2‡m;•ˆ$ë“É´c›f´ÖOf}‹*íë\[—¯“ËÖÙ…ÛgËTü¶ÆÌÐk¢G1¬YQÉJÄÜTÖu"–±ÏËg¥ý±Fã÷¶Ž_ªO’£r|4¿Å¤¦œßkQ2N½2èíØµckÚÆdjòÐÂüQ+×!Þ7ék«Ùn/ûÅd½~™ðAôžËOéœ×üÿüR¬ƒâÅ[:¹Û¾f¹¤Ý8Ø\qÜÐwíó»^¹°Ê(Ïʸÿz”;D=ÎW™¿ᥰG}3$i­W÷ƒ$Ò44?êÕLrx`ú7ú&I§2?ˆÒ¹¹4ô£‰“˜þbÏ2&ïhLt–ÙqDü–?ŠHË Z¯õº|üY³«c²úžH<äÌ@3ÚLŸÉgM`´[Y÷ø±ÜlÞ ÌÌlíΟú[¾ Æ¿dùÖ8öå¸Ú §Ñr5Õ‚SI^¹réÒÕïl™ó¸ǧ­Ê˜“©ñ=ÕŸ=Wú““š ÕZ}PØVËGN6\‡®gƒi×z5ß7&LM˜'¾_?´œØÉÄáNÿFž™vY¦ó³&ôý m^H’Nÿب-å|jOŸ<«µ¿OzͶvû´²´2ôNø¾¾¶º×»Ýëã>¥úéô{IÇ+¹´Ê›ƒV¹’¯.å£G¥3\ȆéôÉ“ÓùÉöÉ|ëæÍ;?ÐmçþŸêýÞîýN½a5<§ºÔc½¹¿žëkkcãÎÆF9þñö¿å=¹§÷ÏífÛÂj~ÿiZm~wÚçN¶k^7îIlLœèñBO£˜õ23Æh¡ãL†íéÙ$Ž“Y=¾Ò˲ޱù uZZÑú¢™¥y~Ob™#ãŒãpœ{A&m­×ÜûS¿7QÛ;Ëiž ÷d_ö¼>hB'\èÏ.çùc-Gçœ/ óÖË,Õ„ö~EíÈ芬³Èk4›­Ðrü¸ÅiØO]¿¥‹®Ýl6·iÙ^,ãÿs–ÜÖñtdb½2ΫÖ(¯´¾QÍ}¤;oœÎOo™ÍÍq.ÕÕG£\ªþå•é£/MgXïNé™ìÎw†ÃÎÖuÝîÞº%»[àÙãõ‰Hí+"õ@]Uzn}_½/ÒxY¤)¡ßÓü‡ˆ½®>q•Û•¿>ÈÕ6¸ë{üEÄ[Sú»­Ù=®Àÿ‡Ô¥&åÖ«,Õb×[eŸúQ¶â{^¹1:n?,Þ(~TÜ*Þ,~\¼Uü¤¸½ïs›Å/Š_¿*ÞÕòoÔïªúßïÞß/þPü±¸3*o=rƒÙÜò’”™ÑÖÜhÈa9!§å)yZ¾(ÏÊóre{[¯–µŸ“³£Ú‹r©¬-®ìßL&ë¡mpå›ÕÝ–$²“– -'UÙÖÒL™½ OkRYªÊu‰´µã²¥Ÿ¸\•ZþnU¶µüó³ç.œöìâÅË'ÖŸ~õµ—®}ýáÚásrAÎk ÎÊ¢vü²|Y¾!ßÒ/~Y¾*ßþ”ë'd]ƒôª¼¦A½&Ÿö ÿû'Ê<÷ÏÚ'zQvcs¸ Oí³zVž¿^»-MâëºËè8~äI½awÛö't“5ý®+ziMúòqm¦ú…ºXé>¼÷b|æ_29¾ñÃ¥¯ßyßþûößd[>ÖÓþÎêòŸí r endstream endobj 30 0 obj << /Type /ExtGState /SA false /SM 0.02 /TR /Identity >> endobj 1 0 obj << /Type /Pages /Kids [ 5 0 R ] /Count 1 >> endobj 2 0 obj << /CreationDate (D:20061105011133) /Producer (Acrobat Distiller 4.0 for Windows) /ModDate (D:20061105011215+09'00') >> endobj xref 0 3 0000000000 65535 f 0000051809 00000 n 0000051873 00000 n trailer << /Size 3 /ID[<21b37df8f836949f6a724722f5ba950d><21b37df8f836949f6a724722f5ba950d>] >> startxref 173 %%EOF qdbm-1.8.78/misc/icon16.png0000644000175000017500000000052307645737602014324 0ustar mikiomikio‰PNG  IHDR(-ScPLTEÿÿÿ jjjzzz–––®®®ÆÆÆ***ÒÒÒÖÖÖF:‚êêêBBBNNNbV’^zr¦.rRRRîîîþþþZZZ¦¦¦ºººŠŠŠåâërrr–޶²«Æ†††fffÊÆÚ?m¤!tRNS@æØfbKGDˆH pHYs  d_‘|IDATxœUÎÛƒ DQñV/Tä´ÓÚTþÿ+¥`,ìÇ•L2U%ë”lÆ*¶#µÏíXæ/Ÿàµµüêº÷ÒGðİ$ïBˆ&‚V€[ŸCû©¨÷¦Àü'Š2Bš3ðjâôågiòì²I­Ä ›<¶ájùÁfnWáúþ &â?‚†IEND®B`‚qdbm-1.8.78/misc/VCmakefile-old0000644000175000017500000000756410025465446015226 0ustar mikiomikio# Makefile to build QDBM using Microsoft Visual C++ #================================================================ # Setting Variables #================================================================ # Targets MYLIBS = qdbm.lib LIBOBJS = depot.obj curia.obj relic.obj hovel.obj \ cabin.obj villa.obj vista.obj odeum.obj myconf.obj MYBINS = dpmgr.exe dptest.exe dptsv.exe crmgr.exe crtest.exe crtsv.exe \ rlmgr.exe rltest.exe hvmgr.exe hvtest.exe cbtest.exe cbcodec.exe \ vlmgr.exe vltest.exe vltsv.exe odmgr.exe odtest.exe odidx.exe # VC++ directory VCPATH = C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7 # Building binaries CLFLAGS = /I "$(VCPATH)\Include" /I "$(VCPATH)\PlatformSDK\Include" /I "." /O2 /nologo LIBFLAGS = /libpath:"$(VCPATH)\lib" /libpath:"$(VCPATH)\PlatformSDK\Lib" /libpath:"." /nologo LINKFLAGS = /libpath:"$(VCPATH)\lib" /libpath:"$(VCPATH)\PlatformSDK\Lib" /libpath:"." /nologo #================================================================ # Suffix rules #================================================================ .SUFFIXES : .SUFFIXES : .c .obj .c.obj : cl /c $(CLFLAGS) $< #================================================================ # Actions #================================================================ all : $(MYLIBS) $(MYBINS) clean : del *.obj *.lib *.dll *.exp *.exe #================================================================ # Building binaries #================================================================ qdbm.lib : $(LIBOBJS) lib $(LIBFLAGS) /OUT:$@ $(LIBOBJS) dpmgr.exe : dpmgr.obj qdbm.lib link $(LINKFLAGS) /OUT:$@ dpmgr.obj qdbm.lib dptest.exe : dptest.obj qdbm.lib link $(LINKFLAGS) /OUT:$@ dptest.obj qdbm.lib dptsv.exe : dptsv.obj qdbm.lib link $(LINKFLAGS) /OUT:$@ dptsv.obj qdbm.lib crmgr.exe : crmgr.obj qdbm.lib link $(LINKFLAGS) /OUT:$@ crmgr.obj qdbm.lib crtest.exe : crtest.obj qdbm.lib link $(LINKFLAGS) /OUT:$@ crtest.obj qdbm.lib crtsv.exe : crtsv.obj qdbm.lib link $(LINKFLAGS) /OUT:$@ crtsv.obj qdbm.lib rlmgr.exe : rlmgr.obj qdbm.lib link $(LINKFLAGS) /OUT:$@ rlmgr.obj qdbm.lib rltest.exe : rltest.obj qdbm.lib link $(LINKFLAGS) /OUT:$@ rltest.obj qdbm.lib hvmgr.exe : hvmgr.obj qdbm.lib link $(LINKFLAGS) /OUT:$@ hvmgr.obj qdbm.lib hvtest.exe : hvtest.obj qdbm.lib link $(LINKFLAGS) /OUT:$@ hvtest.obj qdbm.lib cbtest.exe : cbtest.obj qdbm.lib link $(LINKFLAGS) /OUT:$@ cbtest.obj qdbm.lib cbcodec.exe : cbcodec.obj qdbm.lib link $(LINKFLAGS) /OUT:$@ cbcodec.obj qdbm.lib vlmgr.exe : vlmgr.obj qdbm.lib link $(LINKFLAGS) /OUT:$@ vlmgr.obj qdbm.lib vltest.exe : vltest.obj qdbm.lib link $(LINKFLAGS) /OUT:$@ vltest.obj qdbm.lib vltsv.exe : vltsv.obj qdbm.lib link $(LINKFLAGS) /OUT:$@ vltsv.obj qdbm.lib odmgr.exe : odmgr.obj qdbm.lib link $(LINKFLAGS) /OUT:$@ odmgr.obj qdbm.lib odtest.exe : odtest.obj qdbm.lib link $(LINKFLAGS) /OUT:$@ odtest.obj qdbm.lib odidx.exe : odidx.obj qdbm.lib link $(LINKFLAGS) /OUT:$@ odidx.obj qdbm.lib depot.obj : depot.h myconf.h curia.obj : depot.h curia.h myconf.h relic.obj : depot.h relic.h myconf.h hovel.obj : depot.h curia.h hovel.h myconf.h cabin.obj : cabin.h myconf.h villa.obj : depot.h cabin.h villa.h myconf.h vista.obj : depot.h curia.h cabin.h villa.h vista.h myconf.h odeum.obj : depot.h curia.h cabin.h villa.h myconf.h myconf.obj : myconf.h dpmgr.obj dptest.obj dptsv.obj : depot.h cabin.h crmgr.obj crtest.obj crtsv.obj : depot.h curia.h cabin.h rlmgr.obj rltest.obj : depot.h relic.h cabin.h hvmgr.obj hvtest.obj : depot.h curia.h hovel.h cabin.h cbtest.obj cbcodec.obj : cabin.h vlmgr.obj vltest.obj vltsv.obj : depot.h cabin.h villa.h odmgr.obj odtest.obj odidx.obj : depot.h curia.h cabin.h villa.h odeum.h # END OF FILE qdbm-1.8.78/misc/makevcdef0000755000175000017500000000150210357511303014346 0ustar mikiomikio#! /bin/sh #================================================================ # makevcdef # Generator of module definition file for Visual C++ #================================================================ # check arguments file="$1" if [ -f "$file" ] then true else printf 'usage: makevcdef library\n' 1>&2 exit 1 fi # show headers name=`echo $file | sed -e 's/^lib//' -e 's/\..*//'` printf 'EXPORTS\r\n' # show variables nm -g "$file" | grep ' [BDR] ' | sed 's/.* [BDR] //' | grep -v '^_' | sort | uniq | while read name do num=$((num + 1)) printf ' %s = %s DATA\r\n' "$name" "$name" done # show functions nm -g "$file" | grep ' T ' | sed 's/.* T //' | grep -v '^_' | sort | uniq | while read name do num=$((num + 1)) printf ' %s = %s\r\n' "$name" "$name" done # exit normally exit 0 # END OF FILE qdbm-1.8.78/misc/COPYING.txt0000644000175000017500000006446610573416613014376 0ustar mikiomikio GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! qdbm-1.8.78/misc/mymemo-ja.html0000644000175000017500000000202310573416603015262 0ustar mikiomikio My Private Memo for QDBM

QDBMã®ãŸã‚ã®ç§çš„メモ


cygwin+mingwã§ã®ãƒ“ルド環境ã®è¨­å®šæ–¹æ³•

  • Cygwinã®ã‚»ãƒƒãƒˆã‚¢ãƒƒãƒ—時ã«ã€mingwã®gccã¨mingwã®zlibã‚‚é¸æŠžã™ã‚‹ã€‚
  • mingwã®libiconvã¯mingwã®ã‚µã‚¤ãƒˆã‹ã‚‰æ‰‹ã«å…¥ã‚Œã‚‹ã€‚ãã—ã¦ã€*.h 㯠/usr/include/mingw ã®ä¸‹ã«ã€*.dll.a 㯠/lib/mingw ã®ä¸‹ã«ã€*.dll 㯠/binã®ä¸‹ã«ç§»å‹•ã•ã›ã‚‹ã€‚
  • QDBMã®ãƒ“ルド環境ã®è¨­å®šã¯ ./configure --enable-zlib --enable-iconv ã§è¡Œã„ã€ãƒ‘ッケージã®ä½œæˆã¯ make win32pkg ã§è¡Œã†ã€‚

qdbm-1.8.78/myconf.h0000644000175000017500000003121610573416530013217 0ustar mikiomikio/************************************************************************************************* * System configurations for QDBM * Copyright (C) 2000-2007 Mikio Hirabayashi * This file is part of QDBM, Quick Database Manager. * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU * Lesser General Public License as published by the Free Software Foundation; either version * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * You should have received a copy of the GNU Lesser General Public License along with QDBM; if * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. *************************************************************************************************/ #ifndef _MYCONF_H /* duplication check */ #define _MYCONF_H #if defined(__cplusplus) /* export for C++ */ extern "C" { #endif /************************************************************************************************* * system discrimination *************************************************************************************************/ #if defined(__linux__) #define _SYS_LINUX_ #define _QDBM_SYSNAME "Linux" #elif defined(__FreeBSD__) #define _SYS_FREEBSD_ #define _QDBM_SYSNAME "FreeBSD" #elif defined(__NetBSD__) #define _SYS_NETBSD_ #define _QDBM_SYSNAME "NetBSD" #elif defined(__OpenBSD__) #define _SYS_OPENBSD_ #define _QDBM_SYSNAME "OpenBSD" #elif defined(__sun__) #define _SYS_SUNOS_ #define _QDBM_SYSNAME "SunOS" #elif defined(__hpux) #define _SYS_HPUX_ #define _QDBM_SYSNAME "HP-UX" #elif defined(__osf) #define _SYS_TRU64_ #define _QDBM_SYSNAME "Tru64" #elif defined(_AIX) #define _SYS_AIX_ #define _QDBM_SYSNAME "AIX" #elif defined(__APPLE__) && defined(__MACH__) #define _SYS_MACOSX_ #define _QDBM_SYSNAME "Mac OS X" #elif defined(_MSC_VER) #define _SYS_MSVC_ #define _QDBM_SYSNAME "Windows (VC++)" #elif defined(_WIN32) #define _SYS_MINGW_ #define _QDBM_SYSNAME "Windows (MinGW)" #elif defined(__CYGWIN__) #define _SYS_CYGWIN_ #define _QDBM_SYSNAME "Windows (Cygwin)" #elif defined(__riscos__) || defined(__riscos) #define _SYS_RISCOS_ #define _QDBM_SYSNAME "RISC OS" #else #define _SYS_GENERIC_ #define _QDBM_SYSNAME "Generic" #endif /************************************************************************************************* * general headers *************************************************************************************************/ #if defined(_SYS_MSVC_) #include #include #include #include #include #include #include #include #include #include #include #include #include #include #elif defined(_SYS_MINGW_) #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #elif defined(_SYS_CYGWIN_) #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #else #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #endif /************************************************************************************************* * notation of filesystems *************************************************************************************************/ #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_) #define MYPATHCHR '\\' #define MYPATHSTR "\\" #define MYEXTCHR '.' #define MYEXTSTR "." #define MYCDIRSTR "." #define MYPDIRSTR ".." #elif defined(_SYS_RISCOS_) #define MYPATHCHR '.' #define MYPATHSTR "." #define MYEXTCHR '/' #define MYEXTSTR "/" #define MYCDIRSTR "@" #define MYPDIRSTR "^" #else #define MYPATHCHR '/' #define MYPATHSTR "/" #define MYEXTCHR '.' #define MYEXTSTR "." #define MYCDIRSTR "." #define MYPDIRSTR ".." #endif /************************************************************************************************* * for dosish filesystems *************************************************************************************************/ #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_) || defined(_SYS_CYGWIN_) #undef UNICODE #undef open #define \ open(pathname, flags, mode) \ open(pathname, flags | O_BINARY, mode) #define \ lstat(pathname, buf) \ _qdbm_win32_lstat(pathname, buf) int _qdbm_win32_lstat(const char *pathname, struct stat *buf); #else #undef O_BINARY #undef O_TEXT #undef setmode #define O_BINARY 0 #define O_TEXT 1 #define \ setmode(fd, mode) \ (O_BINARY) #endif /************************************************************************************************* * for POSIX thread *************************************************************************************************/ #if defined(MYPTHREAD) #define _qdbm_ptsafe TRUE void *_qdbm_settsd(void *ptr, int size, const void *initval); #else #define _qdbm_ptsafe FALSE #define \ _qdbm_settsd(ptr, size, initval) \ (NULL) #endif /************************************************************************************************* * for systems without file locking *************************************************************************************************/ #if defined(_SYS_RISCOS_) || defined(MYNOLOCK) #undef fcntl #define \ fcntl(fd, cmd, lock) \ (0) #endif /************************************************************************************************* * for systems without mmap *************************************************************************************************/ #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_) || \ defined(_SYS_FREEBSD_) || defined(_SYS_NETBSD_) || defined(_SYS_OPENBSD_) || \ defined(_SYS_AIX_) || defined(_SYS_RISCOS_) || defined(MYNOMMAP) #undef PROT_EXEC #undef PROT_READ #undef PROT_WRITE #undef PROT_NONE #undef MAP_FIXED #undef MAP_SHARED #undef MAP_PRIVATE #undef MAP_FAILED #undef MS_ASYNC #undef MS_SYNC #undef MS_INVALIDATE #undef mmap #undef munmap #undef msync #undef mflush #define PROT_EXEC (1 << 0) #define PROT_READ (1 << 1) #define PROT_WRITE (1 << 2) #define PROT_NONE (1 << 3) #define MAP_FIXED 1 #define MAP_SHARED 2 #define MAP_PRIVATE 3 #define MAP_FAILED ((void *)-1) #define MS_ASYNC (1 << 0) #define MS_SYNC (1 << 1) #define MS_INVALIDATE (1 << 2) #define \ mmap(start, length, prot, flags, fd, offset) \ _qdbm_mmap(start, length, prot, flags, fd, offset) #define \ munmap(start, length) \ _qdbm_munmap(start, length) #define \ msync(start, length, flags) \ _qdbm_msync(start, length, flags) #define \ mflush(start, length, flags) \ _qdbm_msync(start, length, flags) void *_qdbm_mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset); int _qdbm_munmap(void *start, size_t length); int _qdbm_msync(const void *start, size_t length, int flags); #else #undef mflush #define \ mflush(start, length, flags) \ (0) #endif /************************************************************************************************* * for reentrant time routines *************************************************************************************************/ struct tm *_qdbm_gmtime(const time_t *timep, struct tm *result); struct tm *_qdbm_localtime(const time_t *timep, struct tm *result); /************************************************************************************************* * for systems without times *************************************************************************************************/ #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_) #undef times #undef sysconf struct tms { clock_t tms_utime; clock_t tms_stime; clock_t tms_cutime; clock_t tms_cstime; }; #define \ times(buf) \ _qdbm_times(buf) #define \ sysconf(name) \ (CLOCKS_PER_SEC) clock_t _qdbm_times(struct tms *buf); #endif /************************************************************************************************* * for Win32 *************************************************************************************************/ #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_) #undef F_WRLCK #undef F_RDLCK #undef F_SETLK #undef F_SETLKW #undef fcntl #undef ftruncate #undef fsync #undef mkdir #undef rename #define F_WRLCK 0 #define F_RDLCK 1 #define F_SETLK 0 #define F_SETLKW 1 struct flock { int l_type; int l_whence; int l_start; int l_len; int l_pid; }; #define \ fcntl(fd, cmd, lock) \ _qdbm_win32_fcntl(fd, cmd, lock) #define \ ftruncate(fd, length) \ _chsize(fd, length) #define \ fsync(fd) \ (0) #define \ mkdir(pathname, mode) \ mkdir(pathname) #define \ rename(oldpath, newpath) \ (unlink(newpath), rename(oldpath, newpath)) int _qdbm_win32_fcntl(int fd, int cmd, struct flock *lock); #endif #if defined(_SYS_MSVC_) #undef S_ISDIR #undef S_ISREG #undef opendir #undef closedir #undef readdir #define S_ISDIR(x) (x & _S_IFDIR) #define S_ISREG(x) (x & _S_IFREG) struct dirent { char d_name[1024]; }; typedef struct { HANDLE fh; WIN32_FIND_DATA data; struct dirent de; int first; } DIR; #define \ opendir(name) \ _qdbm_win32_opendir(name) #define \ closedir(dir) \ _qdbm_win32_closedir(dir) #define \ readdir(dir) \ _qdbm_win32_readdir(dir) DIR *_qdbm_win32_opendir(const char *name); int _qdbm_win32_closedir(DIR *dir); struct dirent *_qdbm_win32_readdir(DIR *dir); #endif /************************************************************************************************* * for checking information of the system *************************************************************************************************/ int _qdbm_vmemavail(size_t size); /************************************************************************************************* * for ZLIB *************************************************************************************************/ enum { _QDBM_ZMZLIB, _QDBM_ZMRAW, _QDBM_ZMGZIP }; extern char *(*_qdbm_deflate)(const char *, int, int *, int); extern char *(*_qdbm_inflate)(const char *, int, int *, int); extern unsigned int (*_qdbm_getcrc)(const char *, int); /************************************************************************************************* * for LZO *************************************************************************************************/ extern char *(*_qdbm_lzoencode)(const char *, int, int *); extern char *(*_qdbm_lzodecode)(const char *, int, int *); /************************************************************************************************* * for BZIP2 *************************************************************************************************/ extern char *(*_qdbm_bzencode)(const char *, int, int *); extern char *(*_qdbm_bzdecode)(const char *, int, int *); /************************************************************************************************* * for ICONV *************************************************************************************************/ extern char *(*_qdbm_iconv)(const char *, int, const char *, const char *, int *, int *); extern const char *(*_qdbm_encname)(const char *, int); /************************************************************************************************* * common settings *************************************************************************************************/ #undef TRUE #define TRUE 1 #undef FALSE #define FALSE 0 #define sizeof(a) ((int)sizeof(a)) int _qdbm_dummyfunc(void); #if defined(__cplusplus) /* export for C++ */ } #endif #endif /* duplication check */ /* END OF FILE */ qdbm-1.8.78/relic.h0000644000175000017500000001474410573416530013031 0ustar mikiomikio/************************************************************************************************* * The NDBM-compatible API of QDBM * Copyright (C) 2000-2007 Mikio Hirabayashi * This file is part of QDBM, Quick Database Manager. * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU * Lesser General Public License as published by the Free Software Foundation; either version * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * You should have received a copy of the GNU Lesser General Public License along with QDBM; if * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. *************************************************************************************************/ #ifndef _RELIC_H /* duplication check */ #define _RELIC_H #if defined(__cplusplus) /* export for C++ */ extern "C" { #endif #include #include #include #include #include #if defined(_MSC_VER) && !defined(QDBM_INTERNAL) && !defined(QDBM_STATIC) #define MYEXTERN extern __declspec(dllimport) #else #define MYEXTERN extern #endif /************************************************************************************************* * API *************************************************************************************************/ typedef struct { /* type of structure for a database handle */ DEPOT *depot; /* internal database handle */ int dfd; /* file descriptor of a dummy file */ char *dbm_fetch_vbuf; /* buffer for dbm_fetch */ char *dbm_nextkey_kbuf; /* buffer for dbm_nextkey */ } DBM; typedef struct { /* type of structure for a key or a value */ void *dptr; /* pointer to the region */ size_t dsize; /* size of the region */ } datum; enum { /* enumeration for write modes */ DBM_INSERT, /* keep an existing value */ DBM_REPLACE /* overwrite an existing value */ }; /* Get a database handle. `name' specifies the name of a database. The file names are concatenated with suffixes. `flags' is the same as the one of `open' call, although `O_WRONLY' is treated as `O_RDWR' and additional flags except for `O_CREAT' and `O_TRUNC' have no effect. `mode' specifies the mode of the database file as the one of `open' call does. The return value is the database handle or `NULL' if it is not successful. */ DBM *dbm_open(char *name, int flags, int mode); /* Close a database handle. `db' specifies a database handle. Because the region of the closed handle is released, it becomes impossible to use the handle. */ void dbm_close(DBM *db); /* Store a record. `db' specifies a database handle. `key' specifies a structure of a key. `content' specifies a structure of a value. `flags' specifies behavior when the key overlaps, by the following values: `DBM_REPLACE', which means the specified value overwrites the existing one, `DBM_INSERT', which means the existing value is kept. The return value is 0 if it is successful, 1 if it gives up because of overlaps of the key, -1 if other error occurs. */ int dbm_store(DBM *db, datum key, datum content, int flags); /* Delete a record. `db' specifies a database handle. `key' specifies a structure of a key. The return value is 0 if it is successful, -1 if some errors occur. */ int dbm_delete(DBM *db, datum key); /* Retrieve a record. `db' specifies a database handle. `key' specifies a structure of a key. The return value is a structure of the result. If a record corresponds, the member `dptr' of the structure is the pointer to the region of the value. If no record corresponds or some errors occur, `dptr' is `NULL'. `dptr' points to the region related with the handle. The region is available until the next time of calling this function with the same handle. */ datum dbm_fetch(DBM *db, datum key); /* Get the first key of a database. `db' specifies a database handle. The return value is a structure of the result. If a record corresponds, the member `dptr' of the structure is the pointer to the region of the first key. If no record corresponds or some errors occur, `dptr' is `NULL'. `dptr' points to the region related with the handle. The region is available until the next time of calling this function or the function `dbm_nextkey' with the same handle. */ datum dbm_firstkey(DBM *db); /* Get the next key of a database. `db' specifies a database handle. The return value is a structure of the result. If a record corresponds, the member `dptr' of the structure is the pointer to the region of the next key. If no record corresponds or some errors occur, `dptr' is `NULL'. `dptr' points to the region related with the handle. The region is available until the next time of calling this function or the function `dbm_firstkey' with the same handle. */ datum dbm_nextkey(DBM *db); /* Check whether a database has a fatal error or not. `db' specifies a database handle. The return value is true if the database has a fatal error, false if not. */ int dbm_error(DBM *db); /* No effect. `db' specifies a database handle. The return value is 0. The function is only for compatibility. */ int dbm_clearerr(DBM *db); /* Check whether a handle is read-only or not. `db' specifies a database handle. The return value is true if the handle is read-only, or false if not read-only. */ int dbm_rdonly(DBM *db); /* Get the file descriptor of a directory file. `db' specifies a database handle. The return value is the file descriptor of the directory file. */ int dbm_dirfno(DBM *db); /* Get the file descriptor of a data file. `db' specifies a database handle. The return value is the file descriptor of the data file. */ int dbm_pagfno(DBM *db); #undef MYEXTERN #if defined(__cplusplus) /* export for C++ */ } #endif #endif /* duplication check */ /* END OF FILE */ qdbm-1.8.78/dptest.c0000644000175000017500000005155010610630047013216 0ustar mikiomikio/************************************************************************************************* * Test cases of Depot * Copyright (C) 2000-2007 Mikio Hirabayashi * This file is part of QDBM, Quick Database Manager. * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU * Lesser General Public License as published by the Free Software Foundation; either version * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * You should have received a copy of the GNU Lesser General Public License along with QDBM; if * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. *************************************************************************************************/ #include #include #include #include #include #include #include #include #undef TRUE #define TRUE 1 /* boolean true */ #undef FALSE #define FALSE 0 /* boolean false */ #define RECBUFSIZ 32 /* buffer for records */ /* for RISC OS */ #if defined(__riscos__) || defined(__riscos) #include int __riscosify_control = __RISCOSIFY_NO_PROCESS; #endif /* global variables */ const char *progname; /* program name */ /* function prototypes */ int main(int argc, char **argv); void usage(void); int runwrite(int argc, char **argv); int runread(int argc, char **argv); int runrcat(int argc, char **argv); int runcombo(int argc, char **argv); int runwicked(int argc, char **argv); int printfflush(const char *format, ...); void pdperror(const char *name); int myrand(void); int dowrite(const char *name, int rnum, int bnum, int sparse); int doread(const char *name, int wb); int dorcat(const char *name, int rnum, int bnum, int pnum, int align, int fbpsiz, int cb); int docombo(const char *name); int dowicked(const char *name, int rnum, int cb); /* main routine */ int main(int argc, char **argv){ char *env; int rv; cbstdiobin(); if((env = getenv("QDBMDBGFD")) != NULL) dpdbgfd = atoi(env); progname = argv[0]; if(argc < 2) usage(); rv = 0; if(!strcmp(argv[1], "write")){ rv = runwrite(argc, argv); } else if(!strcmp(argv[1], "read")){ rv = runread(argc, argv); } else if(!strcmp(argv[1], "rcat")){ rv = runrcat(argc, argv); } else if(!strcmp(argv[1], "combo")){ rv = runcombo(argc, argv); } else if(!strcmp(argv[1], "wicked")){ rv = runwicked(argc, argv); } else { usage(); } return rv; } /* print the usage and exit */ void usage(void){ fprintf(stderr, "%s: test cases for Depot\n", progname); fprintf(stderr, "\n"); fprintf(stderr, "usage:\n"); fprintf(stderr, " %s write [-s] name rnum bnum\n", progname); fprintf(stderr, " %s read [-wb] name\n", progname); fprintf(stderr, " %s rcat [-c] name rnum bnum pnum align fbpsiz\n", progname); fprintf(stderr, " %s combo name\n", progname); fprintf(stderr, " %s wicked [-c] name rnum\n", progname); fprintf(stderr, "\n"); exit(1); } /* parse arguments of write command */ int runwrite(int argc, char **argv){ char *name, *rstr, *bstr; int i, rnum, bnum, sb, rv; name = NULL; rstr = NULL; bstr = NULL; rnum = 0; bnum = 0; sb = FALSE; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ if(!strcmp(argv[i], "-s")){ sb = TRUE; } else { usage(); } } else if(!name){ name = argv[i]; } else if(!rstr){ rstr = argv[i]; } else if(!bstr){ bstr = argv[i]; } else { usage(); } } if(!name || !rstr || !bstr) usage(); rnum = atoi(rstr); bnum = atoi(bstr); if(rnum < 1 || bnum < 1) usage(); rv = dowrite(name, rnum, bnum, sb); return rv; } /* parse arguments of read command */ int runread(int argc, char **argv){ char *name; int i, wb, rv; name = NULL; wb = FALSE; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ if(!strcmp(argv[i], "-wb")){ wb = TRUE; } else { usage(); } } else if(!name){ name = argv[i]; } else { usage(); } } if(!name) usage(); rv = doread(name, wb); return rv; } /* parse arguments of rcat command */ int runrcat(int argc, char **argv){ char *name, *rstr, *bstr, *pstr, *astr, *fstr; int i, rnum, bnum, pnum, align, fbpsiz, cb, rv; name = NULL; rstr = NULL; bstr = NULL; pstr = NULL; astr = NULL; fstr = NULL; rnum = 0; bnum = 0; pnum = 0; align = 0; fbpsiz = 0; cb = FALSE; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ if(!strcmp(argv[i], "-c")){ cb = TRUE; } else { usage(); } } else if(!name){ name = argv[i]; } else if(!rstr){ rstr = argv[i]; } else if(!bstr){ bstr = argv[i]; } else if(!pstr){ pstr = argv[i]; } else if(!astr){ astr = argv[i]; } else if(!fstr){ fstr = argv[i]; } else { usage(); } } if(!name || !rstr || !bstr || !pstr || !astr || !fstr) usage(); rnum = atoi(rstr); bnum = atoi(bstr); pnum = atoi(pstr); align = atoi(astr); fbpsiz= atoi(fstr); if(rnum < 1 || bnum < 1 || pnum < 1 || fbpsiz < 0) usage(); rv = dorcat(name, rnum, bnum, pnum, align, fbpsiz, cb); return rv; } /* parse arguments of combo command */ int runcombo(int argc, char **argv){ char *name; int i, rv; name = NULL; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ usage(); } else if(!name){ name = argv[i]; } else { usage(); } } if(!name) usage(); rv = docombo(name); return rv; } /* parse arguments of wicked command */ int runwicked(int argc, char **argv){ char *name, *rstr; int i, rnum, cb, rv; name = NULL; rstr = NULL; rnum = 0; cb = FALSE; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ if(!strcmp(argv[i], "-c")){ cb = TRUE; } else { usage(); } } else if(!name){ name = argv[i]; } else if(!rstr){ rstr = argv[i]; } else { usage(); } } if(!name || !rstr) usage(); rnum = atoi(rstr); if(rnum < 1) usage(); rv = dowicked(name, rnum, cb); return rv; } /* print formatted string and flush the buffer */ int printfflush(const char *format, ...){ va_list ap; int rv; va_start(ap, format); rv = vprintf(format, ap); if(fflush(stdout) == EOF) rv = -1; va_end(ap); return rv; } /* print an error message */ void pdperror(const char *name){ fprintf(stderr, "%s: %s: %s\n", progname, name, dperrmsg(dpecode)); } /* pseudo random number generator */ int myrand(void){ static int cnt = 0; if(cnt == 0) srand(time(NULL)); return (rand() * rand() + (rand() >> (sizeof(int) * 4)) + (cnt++)) & INT_MAX; } /* perform write command */ int dowrite(const char *name, int rnum, int bnum, int sparse){ DEPOT *depot; int i, omode, err, len; char buf[RECBUFSIZ]; printfflush("\n name=%s rnum=%d bnum=%d s=%d\n\n", name, rnum, bnum, sparse); /* open a database */ omode = DP_OWRITER | DP_OCREAT | DP_OTRUNC | (sparse ? DP_OSPARSE : 0); if(!(depot = dpopen(name, omode, bnum))){ pdperror(name); return 1; } err = FALSE; /* loop for each record */ for(i = 1; i <= rnum; i++){ /* store a record */ len = sprintf(buf, "%08d", i); if(!dpput(depot, buf, len, buf, len, DP_DOVER)){ pdperror(name); err = TRUE; break; } /* print progression */ if(rnum > 250 && i % (rnum / 250) == 0){ putchar('.'); fflush(stdout); if(i == rnum || i % (rnum / 10) == 0){ printfflush(" (%08d)\n", i); } } } /* close the database */ if(!dpclose(depot)){ pdperror(name); return 1; } if(!err) printfflush("ok\n\n"); return err ? 1 : 0; } /* perform read command */ int doread(const char *name, int wb){ DEPOT *depot; int i, rnum, err, len; char buf[RECBUFSIZ], vbuf[RECBUFSIZ], *val; printfflush("\n name=%s wb=%d\n\n", name, wb); /* open a database */ if(!(depot = dpopen(name, DP_OREADER, -1))){ pdperror(name); return 1; } /* get the number of records */ rnum = dprnum(depot); err = FALSE; /* loop for each record */ for(i = 1; i <= rnum; i++){ /* retrieve a record */ len = sprintf(buf, "%08d", i); if(wb){ if(dpgetwb(depot, buf, len, 0, RECBUFSIZ, vbuf) == -1){ pdperror(name); err = TRUE; break; } } else { if(!(val = dpget(depot, buf, len, 0, -1, NULL))){ pdperror(name); err = TRUE; break; } free(val); } /* print progression */ if(rnum > 250 && i % (rnum / 250) == 0){ putchar('.'); fflush(stdout); if(i == rnum || i % (rnum / 10) == 0){ printfflush(" (%08d)\n", i); } } } /* close the database */ if(!dpclose(depot)){ pdperror(name); return 1; } if(!err) printfflush("ok\n\n"); return err ? 1 : 0; } /* perform rcat command */ int dorcat(const char *name, int rnum, int bnum, int pnum, int align, int fbpsiz, int cb){ DEPOT *depot; CBMAP *map; int i, err, len, ksiz, vsiz, rsiz; const char *kbuf, *vbuf; char buf[RECBUFSIZ], *rbuf; printfflush("\n name=%s rnum=%d bnum=%d pnum=%d align=%d" " fbpsiz=%d c=%d\n\n", name, rnum, bnum, pnum, align, fbpsiz, cb); if(!(depot = dpopen(name, DP_OWRITER | DP_OCREAT | DP_OTRUNC, bnum))){ pdperror(name); return 1; } if(!dpsetalign(depot, align) || !dpsetfbpsiz(depot, fbpsiz)){ pdperror(name); dpclose(depot); return 1; } map = NULL; if(cb) map = cbmapopen(); err = FALSE; for(i = 1; i <= rnum; i++){ len = sprintf(buf, "%08d", myrand() % pnum + 1); if(!dpput(depot, buf, len, buf, len, DP_DCAT)){ pdperror(name); err = TRUE; break; } if(map) cbmapputcat(map, buf, len, buf, len); if(rnum > 250 && i % (rnum / 250) == 0){ putchar('.'); fflush(stdout); if(i == rnum || i % (rnum / 10) == 0){ printfflush(" (%08d: fsiz=%d rnum=%d)\n", i, dpfsiz(depot), dprnum(depot)); } } } if(map){ printfflush("Matching records ... "); cbmapiterinit(map); while((kbuf = cbmapiternext(map, &ksiz)) != NULL){ vbuf = cbmapget(map, kbuf, ksiz, &vsiz); if(!(rbuf = dpget(depot, kbuf, ksiz, 0, -1, &rsiz))){ pdperror(name); err = TRUE; break; } if(rsiz != vsiz || memcmp(rbuf, vbuf, rsiz)){ fprintf(stderr, "%s: %s: unmatched record\n", progname, name); free(rbuf); err = TRUE; break; } free(rbuf); } cbmapclose(map); if(!err) printfflush("ok\n"); } if(!dpclose(depot)){ pdperror(name); return 1; } if(!err) printfflush("ok\n\n"); return err ? 1 : 0; } /* perform combo command */ int docombo(const char *name){ DEPOT *depot; char buf[RECBUFSIZ], wbuf[RECBUFSIZ], *vbuf; int i, len, wlen, vsiz; printfflush("\n name=%s\n\n", name); printfflush("Creating a database with bnum 3 ... "); if(!(depot = dpopen(name, DP_OWRITER | DP_OCREAT | DP_OTRUNC, 3))){ pdperror(name); return 1; } printfflush("ok\n"); printfflush("Setting alignment as 16 ... "); if(!dpsetalign(depot, 16)){ pdperror(name); dpclose(depot); return 1; } printfflush("ok\n"); printfflush("Adding 20 records ... "); for(i = 1; i <= 20; i++){ len = sprintf(buf, "%08d", i); if(!dpput(depot, buf, len, buf, len, DP_DOVER)){ pdperror(name); dpclose(depot); return 1; } } printfflush("ok\n"); printfflush("Checking records ... "); for(i = 1; i <= 20; i++){ len = sprintf(buf, "%08d", i); if(!(vbuf = dpget(depot, buf, len, 0, -1, &vsiz))){ pdperror(name); dpclose(depot); return 1; } free(vbuf); if(vsiz != dpvsiz(depot, buf, len)){ fprintf(stderr, "%s: %s: invalid vsiz\n", progname, name); dpclose(depot); return 1; } } printfflush("ok\n"); printfflush("Overwriting top 10 records without moving rooms ... "); for(i = 1; i <= 10; i++){ len = sprintf(buf, "%08d", i); if(!dpput(depot, buf, len, buf, len, DP_DOVER)){ pdperror(name); dpclose(depot); return 1; } } printfflush("ok\n"); printfflush("Overwriting top 5 records with moving rooms ... "); for(i = 1; i <= 5; i++){ len = sprintf(buf, "%08d", i); wlen = sprintf(wbuf, "%024d", i); if(!dpput(depot, buf, len, wbuf, wlen, DP_DOVER)){ pdperror(name); dpclose(depot); return 1; } } printfflush("ok\n"); printfflush("Overwriting top 15 records in concatenation with moving rooms ... "); for(i = 1; i <= 15; i++){ len = sprintf(buf, "%08d", i); wlen = sprintf(wbuf, "========================"); if(!dpput(depot, buf, len, wbuf, wlen, DP_DCAT)){ pdperror(name); dpclose(depot); return 1; } } printfflush("ok\n"); printfflush("Checking records ... "); for(i = 1; i <= 20; i++){ len = sprintf(buf, "%08d", i); if(!(vbuf = dpget(depot, buf, len, 0, -1, &vsiz))){ pdperror(name); dpclose(depot); return 1; } free(vbuf); if(vsiz != dpvsiz(depot, buf, len)){ fprintf(stderr, "%s: %s: invalid vsiz\n", progname, name); dpclose(depot); return 1; } } printfflush("ok\n"); printfflush("Deleting top 10 records ... "); for(i = 1; i <= 10; i++){ len = sprintf(buf, "%08d", i); if(!dpout(depot, buf, len)){ pdperror(name); dpclose(depot); return 1; } } printfflush("ok\n"); printfflush("Checking deleted records ... "); for(i = 1; i <= 10; i++){ len = sprintf(buf, "%08d", i); vbuf = dpget(depot, buf, len, 0, -1, &vsiz); free(vbuf); if(vbuf || dpecode != DP_ENOITEM){ fprintf(stderr, "%s: %s: deleting failed\n", progname, name); dpclose(depot); return 1; } } printfflush("ok\n"); printfflush("Overwriting top 15 records in concatenation with moving rooms ... "); for(i = 1; i <= 15; i++){ len = sprintf(buf, "%08d", i); wlen = sprintf(wbuf, "========================"); if(!dpput(depot, buf, len, wbuf, wlen, DP_DCAT)){ pdperror(name); dpclose(depot); return 1; } } printfflush("ok\n"); printfflush("Checking records ... "); for(i = 1; i <= 20; i++){ len = sprintf(buf, "%08d", i); if(!(vbuf = dpget(depot, buf, len, 0, -1, &vsiz))){ pdperror(name); dpclose(depot); return 1; } free(vbuf); if(vsiz != dpvsiz(depot, buf, len)){ fprintf(stderr, "%s: %s: invalid vsiz\n", progname, name); dpclose(depot); return 1; } } printfflush("ok\n"); printfflush("Optimizing the database ... "); if(!dpoptimize(depot, -1)){ pdperror(name); dpclose(depot); return 1; } printfflush("ok\n"); printfflush("Checking records ... "); for(i = 1; i <= 20; i++){ len = sprintf(buf, "%08d", i); if(!(vbuf = dpget(depot, buf, len, 0, -1, &vsiz))){ pdperror(name); dpclose(depot); return 1; } free(vbuf); if(vsiz != dpvsiz(depot, buf, len)){ fprintf(stderr, "%s: %s: invalid vsiz\n", progname, name); dpclose(depot); return 1; } } printfflush("ok\n"); printfflush("Closing the database ... "); if(!dpclose(depot)){ pdperror(name); return 1; } printfflush("ok\n"); printfflush("Creating a database with bnum 1000000 ... "); if(!(depot = dpopen(name, DP_OWRITER | DP_OCREAT | DP_OTRUNC, 1000000))){ pdperror(name); return 1; } printfflush("ok\n"); printfflush("Adding 1000 records ... "); for(i = 1; i <= 1000; i++){ len = sprintf(buf, "%08d", i); if(!dpput(depot, buf, len, buf, len, DP_DOVER)){ pdperror(name); dpclose(depot); return 1; } } printfflush("ok\n"); printfflush("Adding 64 records ... "); for(i = 1; i <= 1000; i++){ len = sprintf(buf, "%o", i); if(!dpput(depot, buf, len, buf, len, DP_DOVER)){ pdperror(name); dpclose(depot); return 1; } } printfflush("ok\n"); printfflush("Syncing the database ... "); if(!dpsync(depot)){ pdperror(name); dpclose(depot); return 1; } printfflush("ok\n"); printfflush("Retrieving records directly ... "); for(i = 1; i <= 64; i++){ len = sprintf(buf, "%o", i); if(!(vbuf = dpsnaffle(name, buf, len, &vsiz))){ pdperror(name); dpclose(depot); return 1; } if(strcmp(vbuf, buf)){ fprintf(stderr, "%s: %s: invalid content\n", progname, name); free(vbuf); dpclose(depot); return 1; } free(vbuf); if(vsiz != dpvsiz(depot, buf, len)){ fprintf(stderr, "%s: %s: invalid vsiz\n", progname, name); dpclose(depot); return 1; } } printfflush("ok\n"); printfflush("Optimizing the database ... "); if(!dpoptimize(depot, -1)){ pdperror(name); dpclose(depot); return 1; } printfflush("ok\n"); printfflush("Closing the database ... "); if(!dpclose(depot)){ pdperror(name); return 1; } printfflush("ok\n"); printfflush("all ok\n\n"); return 0; } /* perform wicked command */ int dowicked(const char *name, int rnum, int cb){ DEPOT *depot; CBMAP *map; int i, len, err, align, mksiz, mvsiz, rsiz; const char *mkbuf, *mvbuf; char buf[RECBUFSIZ], vbuf[RECBUFSIZ], *val; printfflush("\n name=%s rnum=%d\n\n", name, rnum); err = FALSE; if(!(depot = dpopen(name, DP_OWRITER | DP_OCREAT | DP_OTRUNC, rnum / 10))){ pdperror(name); return 1; } if(!dpsetalign(depot, 16) || !dpsetfbpsiz(depot, 256)){ pdperror(name); err = TRUE; } map = NULL; if(cb) map = cbmapopen(); for(i = 1; i <= rnum; i++){ len = sprintf(buf, "%08d", myrand() % rnum + 1); switch(myrand() % 16){ case 0: putchar('O'); if(!dpput(depot, buf, len, buf, len, DP_DOVER)) err = TRUE; if(map) cbmapput(map, buf, len, buf, len, TRUE); break; case 1: putchar('K'); if(!dpput(depot, buf, len, buf, len, DP_DKEEP) && dpecode != DP_EKEEP) err = TRUE; if(map) cbmapput(map, buf, len, buf, len, FALSE); break; case 2: putchar('D'); if(!dpout(depot, buf, len) && dpecode != DP_ENOITEM) err = TRUE; if(map) cbmapout(map, buf, len); break; case 3: putchar('G'); if(dpgetwb(depot, buf, len, 2, RECBUFSIZ, vbuf) == -1 && dpecode != DP_ENOITEM) err = TRUE; break; case 4: putchar('V'); if(dpvsiz(depot, buf, len) == -1 && dpecode != DP_ENOITEM) err = TRUE; break; default: putchar('C'); if(!dpput(depot, buf, len, buf, len, DP_DCAT)) err = TRUE; if(map) cbmapputcat(map, buf, len, buf, len); break; } if(i % 50 == 0) printfflush(" (%08d)\n", i); if(!err && rnum > 100 && myrand() % (rnum / 100) == 0){ if(myrand() % 10 == 0){ align = (myrand() % 4 + 1) * -1; } else { align = myrand() % 32; } if(!dpsetalign(depot, align)) err = TRUE; } if(err){ pdperror(name); break; } } if(!dpoptimize(depot, -1)){ pdperror(name); err = TRUE; } for(i = 1; i <= rnum; i++){ len = sprintf(buf, "%08d", i); if(!dpput(depot, buf, len, ":", -1, DP_DCAT)){ pdperror(name); err = TRUE; break; } if(map) cbmapputcat(map, buf, len, ":", -1); putchar(':'); if(i % 50 == 0) printfflush(" (%08d)\n", i); } if(!dpoptimize(depot, -1)){ pdperror(name); err = TRUE; } for(i = 1; i <= rnum; i++){ len = sprintf(buf, "%08d", i); if(!(val = dpget(depot, buf, len, 0, -1, NULL))){ pdperror(name); err = TRUE; break; } free(val); putchar('='); if(i % 50 == 0) printfflush(" (%08d)\n", i); } if(!dpiterinit(depot)){ pdperror(name); err = TRUE; } for(i = 1; i <= rnum; i++){ if(!(val = dpiternext(depot, NULL))){ pdperror(name); err = TRUE; break; } free(val); putchar('@'); if(i % 50 == 0) printfflush(" (%08d)\n", i); } if(map){ printfflush("Matching records ... "); cbmapiterinit(map); while((mkbuf = cbmapiternext(map, &mksiz)) != NULL){ mvbuf = cbmapget(map, mkbuf, mksiz, &mvsiz); if(!(val = dpget(depot, mkbuf, mksiz, 0, -1, &rsiz))){ pdperror(name); err = TRUE; break; } if(rsiz != mvsiz || memcmp(val, mvbuf, rsiz)){ fprintf(stderr, "%s: %s: unmatched record\n", progname, name); free(val); err = TRUE; break; } free(val); } cbmapclose(map); if(!err) printfflush("ok\n"); } if(!dpclose(depot)){ pdperror(name); return 1; } if(!err) printfflush("ok\n\n"); return err ? 1 : 0; } /* END OF FILE */ qdbm-1.8.78/odidx.c0000644000175000017500000006245610610627747013046 0ustar mikiomikio/************************************************************************************************* * Utility for indexing document files into a database of Odeum * Copyright (C) 2000-2007 Mikio Hirabayashi * This file is part of QDBM, Quick Database Manager. * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU * Lesser General Public License as published by the Free Software Foundation; either version * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * You should have received a copy of the GNU Lesser General Public License along with QDBM; if * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. *************************************************************************************************/ #include #include #include #include #include #include #include #include #include #undef TRUE #define TRUE 1 /* boolean true */ #undef FALSE #define FALSE 0 /* boolean false */ #define PATHCHR '/' /* delimiter character of path */ #define EXTCHR '.' /* delimiter character of extension */ #define CDIRSTR "." /* string of current directory */ #define PDIRSTR ".." /* string of parent directory */ #define MTDBNAME "_mtime" /* name of the database for last modified times */ #define MTDBLRM 81 /* records in a leaf node of time database */ #define MTDBNIM 192 /* records in a non-leaf node of time database */ #define MTDBLCN 64 /* number of leaf cache of time database */ #define MTDBNCN 32 /* number of non-leaf cache of time database */ #define SCDBNAME "_score" /* name of the database for scores */ #define SCDBBNUM 32749 /* bucket number of the score database */ #define SCDBALIGN -3 /* alignment of the score database */ #define PATHBUFSIZ 2048 /* size of a path buffer */ #define MAXLOAD 0.85 /* max ratio of bucket loading */ #define KEYNUM 32 /* number of keywords to store */ /* for Win32 and RISC OS */ #if defined(_WIN32) #undef PATHCHR #define PATHCHR '\\' #undef EXTCHR #define EXTCHR '.' #undef CDIRSTR #define CDIRSTR "." #undef PDIRSTR #define PDIRSTR ".." #elif defined(__riscos__) || defined(__riscos) #include int __riscosify_control = __RISCOSIFY_NO_PROCESS; #undef PATHCHR #define PATHCHR '.' #undef EXTCHR #define EXTCHR '/' #undef CDIRSTR #define CDIRSTR "@" #undef PDIRSTR #define PDIRSTR "^" #endif /* global variables */ const char *progname; /* program name */ int sigterm; /* flag for termination signal */ /* function prototypes */ int main(int argc, char **argv); void setsignals(void); void sigtermhandler(int num); void usage(void); int runregister(int argc, char **argv); int runrelate(int argc, char **argv); int runpurge(int argc, char **argv); int bwimatchlist(const char *str, const CBLIST *keys); char *fgetl(FILE *ifp); void otcb(const char *fname, ODEUM *odeum, const char *msg); void pdperror(const char *name); void printferror(const char *format, ...); void printfinfo(const char *format, ...); const char *datestr(time_t t); int proclist(const char *name, const char *lfile, int wmax, const CBLIST *tsuflist, const CBLIST *hsuflist); int procdir(const char *name, const char *dir, int wmax, const CBLIST *tsuflist, const CBLIST *hsuflist); int indexdir(ODEUM *odeum, VILLA *mtdb, const char *name, const char *dir, int wmax, const CBLIST *tsuflist, const CBLIST *hsuflist); int indexfile(ODEUM *odeum, VILLA *mtdb, const char *name, const char *file, int wmax, const CBLIST *tsuflist, const CBLIST *hsuflist); char *filetouri(const char *file); ODDOC *makedocplain(const char *uri, const char *text, const char *date); ODDOC *makedochtml(const char *uri, const char *html, const char *date); CBMAP *htmlescpairs(void); int procrelate(const char *name); int procpurge(const char *name); /* main routine */ int main(int argc, char **argv){ int rv; cbstdiobin(); progname = argv[0]; sigterm = FALSE; setsignals(); if(argc < 2) usage(); odsetotcb(otcb); rv = 0; if(!strcmp(argv[1], "register")){ rv = runregister(argc, argv); } else if(!strcmp(argv[1], "relate")){ rv = runrelate(argc, argv); } else if(!strcmp(argv[1], "purge")){ rv = runpurge(argc, argv); } else { usage(); } return rv; } /* set signal handlers */ void setsignals(void){ signal(1, sigtermhandler); signal(2, sigtermhandler); signal(3, sigtermhandler); signal(13, sigtermhandler); signal(15, sigtermhandler); } /* handler of termination signal */ void sigtermhandler(int num){ signal(num, SIG_DFL); sigterm = TRUE; printfinfo("the termination signal %d catched", num); } /* print the usage and exit */ void usage(void){ fprintf(stderr, "%s: indexer of document files\n", progname); fprintf(stderr, "\n"); fprintf(stderr, "usage:\n"); fprintf(stderr, " %s register [-l file] [-wmax num] [-tsuf sufs] [-hsuf sufs] name [dir]\n", progname); fprintf(stderr, " %s relate name\n", progname); fprintf(stderr, " %s purge name\n", progname); fprintf(stderr, "\n"); exit(1); } /* parse arguments of register command */ int runregister(int argc, char **argv){ char *name, *dir, *lfile, *tsuf, *hsuf, path[PATHBUFSIZ]; int i, wmax, plen, rv; CBLIST *tsuflist, *hsuflist; name = NULL; dir = NULL; lfile = NULL; tsuf = NULL; hsuf = NULL; wmax = -1; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ if(!strcmp(argv[i], "-l")){ if(++i >= argc) usage(); lfile = argv[i]; } else if(!strcmp(argv[i], "-wmax")){ if(++i >= argc) usage(); wmax = atoi(argv[i]); } else if(!strcmp(argv[i], "-tsuf")){ if(++i >= argc) usage(); tsuf = argv[i]; } else if(!strcmp(argv[i], "-hsuf")){ if(++i >= argc) usage(); hsuf = argv[i]; } else { usage(); } } else if(!name){ name = argv[i]; } else if(!dir){ dir = argv[i]; } else { usage(); } } if(!name) usage(); if(!dir) dir = CDIRSTR; plen = sprintf(path, "%s", dir); if(plen > 1 && path[plen-1] == PATHCHR) path[plen-1] = '\0'; tsuflist = cbsplit(tsuf ? tsuf : ".txt,.text", -1, ","); hsuflist = cbsplit(hsuf ? hsuf : ".html,.htm", -1, ","); if(lfile){ rv = proclist(name, lfile, wmax, tsuflist, hsuflist); } else { rv = procdir(name, path, wmax, tsuflist, hsuflist); } cblistclose(hsuflist); cblistclose(tsuflist); return rv; } /* parse arguments of relate command */ int runrelate(int argc, char **argv){ char *name; int i, rv; name = NULL; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ usage(); } else if(!name){ name = argv[i]; } else { usage(); } } if(!name) usage(); rv = procrelate(name); return rv; } /* parse arguments of purge command */ int runpurge(int argc, char **argv){ char *name; int i, rv; name = NULL; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ usage(); } else if(!name){ name = argv[i]; } else { usage(); } } if(!name) usage(); rv = procpurge(name); return rv; } /* case insensitive backward matching with a list */ int bwimatchlist(const char *str, const CBLIST *keys){ int i; for(i = 0; i < cblistnum(keys); i++){ if(cbstrbwimatch(str, cblistval(keys, i, NULL))) return TRUE; } return FALSE; } /* read a line */ char *fgetl(FILE *ifp){ char *buf; int c, len, blen; buf = NULL; len = 0; blen = 256; while((c = fgetc(ifp)) != EOF){ if(blen <= len) blen *= 2; buf = cbrealloc(buf, blen + 1); if(c == '\n') c = '\0'; buf[len++] = c; if(c == '\0') break; } if(!buf) return NULL; buf[len] = '\0'; return buf; } /* report the outturn */ void otcb(const char *fname, ODEUM *odeum, const char *msg){ char *name; name = odname(odeum); printf("%s: %s: %s: %s\n", progname, fname, name, msg); free(name); } /* print an error message */ void pdperror(const char *name){ printf("%s: ERROR: %s: %s\n", progname, name, dperrmsg(dpecode)); fflush(stdout); } /* print formatted error string and flush the buffer */ void printferror(const char *format, ...){ va_list ap; va_start(ap, format); printf("%s: ERROR: ", progname); vprintf(format, ap); putchar('\n'); fflush(stdout); va_end(ap); } /* print formatted information string and flush the buffer */ void printfinfo(const char *format, ...){ va_list ap; va_start(ap, format); printf("%s: INFO: ", progname); vprintf(format, ap); putchar('\n'); fflush(stdout); va_end(ap); } /* get static string of the date */ const char *datestr(time_t t){ static char buf[32]; struct tm *stp; if(!(stp = localtime(&t))) return "0000/00/00 00:00:00"; sprintf(buf, "%04d/%02d/%02d %02d:%02d:%02d", stp->tm_year + 1900, stp->tm_mon + 1, stp->tm_mday, stp->tm_hour, stp->tm_min, stp->tm_sec); return buf; } /* processing with finding files in a list file */ int proclist(const char *name, const char *lfile, int wmax, const CBLIST *tsuflist, const CBLIST *hsuflist){ ODEUM *odeum; VILLA *mtdb; FILE *ifp; char *line, path[PATHBUFSIZ]; int err, fatal; if(!strcmp(lfile, "-")){ ifp = stdin; } else { if(!(ifp = fopen(lfile, "rb"))){ printferror("%s: file cannot be opened", lfile); return 1; } } printfinfo("%s: registration started", name); if(!(odeum = odopen(name, OD_OWRITER | OD_OCREAT))){ pdperror(name); if(ifp != stdin) fclose(ifp); return 1; } sprintf(path, "%s%c%s", name, PATHCHR, MTDBNAME); if(!(mtdb = vlopen(path, VL_OWRITER | VL_OCREAT, VL_CMPLEX))){ pdperror(name); odclose(odeum); if(ifp != stdin) fclose(ifp); return 1; } vlsettuning(mtdb, MTDBLRM, MTDBNIM, MTDBLCN, MTDBNCN); printfinfo("%s: database opened: fsiz=%.0f dnum=%d wnum=%d bnum=%d", name, odfsiz(odeum), oddnum(odeum), odwnum(odeum), odbnum(odeum)); err = FALSE; while((line = fgetl(ifp)) != NULL){ if(sigterm){ printferror("aborting due to a termination signal"); free(line); err = TRUE; break; } if(!indexfile(odeum, mtdb, name, line, wmax, tsuflist, hsuflist)) err = TRUE; free(line); } fatal = odfatalerror(odeum); printfinfo("%s: database closing: fsiz=%.0f dnum=%d wnum=%d bnum=%d", name, odfsiz(odeum), oddnum(odeum), odwnum(odeum), odbnum(odeum)); if(!vlclose(mtdb)){ pdperror(name); err = TRUE; } if(!odclose(odeum)){ pdperror(name); err = TRUE; } if(ifp != stdin) fclose(ifp); if(err){ printfinfo("%s: registration was over%s", name, fatal ? " with fatal error" : ""); } else { printfinfo("%s: registration completed successfully", name); } return err ? 1 : 0; } /* processing with finding files in a directory */ int procdir(const char *name, const char *dir, int wmax, const CBLIST *tsuflist, const CBLIST *hsuflist){ ODEUM *odeum; VILLA *mtdb; char path[PATHBUFSIZ]; int err, fatal; printfinfo("%s: registration started", name); if(!(odeum = odopen(name, OD_OWRITER | OD_OCREAT))){ pdperror(name); return 1; } sprintf(path, "%s%c%s", name, PATHCHR, MTDBNAME); if(!(mtdb = vlopen(path, VL_OWRITER | VL_OCREAT, VL_CMPLEX))){ pdperror(name); odclose(odeum); return 1; } vlsettuning(mtdb, MTDBLRM, MTDBNIM, MTDBLCN, MTDBNCN); printfinfo("%s: database opened: fsiz=%.0f dnum=%d wnum=%d bnum=%d", name, odfsiz(odeum), oddnum(odeum), odwnum(odeum), odbnum(odeum)); err = FALSE; if(!indexdir(odeum, mtdb, name, dir, wmax, tsuflist, hsuflist)) err = TRUE; fatal = odfatalerror(odeum); printfinfo("%s: database closing: fsiz=%.0f dnum=%d wnum=%d bnum=%d", name, odfsiz(odeum), oddnum(odeum), odwnum(odeum), odbnum(odeum)); if(!vlclose(mtdb)){ pdperror(name); err = TRUE; } if(!odclose(odeum)){ pdperror(name); err = TRUE; } if(err){ printfinfo("%s: registration was over%s", name, fatal ? " with fatal error" : ""); } else { printfinfo("%s: registration completed successfully", name); } return err ? 1 : 0; } /* find and index files in a directory */ int indexdir(ODEUM *odeum, VILLA *mtdb, const char *name, const char *dir, int wmax, const CBLIST *tsuflist, const CBLIST *hsuflist){ CBLIST *files; const char *file; char path[PATHBUFSIZ]; int i, isroot, isdir, err; if(!(files = cbdirlist(dir))){ printferror("%s: directory cannot be opened", dir); return FALSE; } isroot = dir[0] == PATHCHR && dir[1] == '\0'; err = FALSE; for(i = 0; i < cblistnum(files); i++){ if(sigterm){ printferror("aborting due to a termination signal"); cblistclose(files); return FALSE; } file = cblistval(files, i, NULL); if(!strcmp(file, CDIRSTR) || !strcmp(file, PDIRSTR)) continue; if(isroot){ sprintf(path, "%s%s", dir, file); } else { sprintf(path, "%s%c%s", dir, PATHCHR, file); } if(!cbfilestat(path, &isdir, NULL, NULL)){ printferror("%s: file does not exist", file); err = TRUE; continue; } if(isdir){ if(!indexdir(odeum, mtdb, name, path, wmax, tsuflist, hsuflist)) err = TRUE; } else { if(!indexfile(odeum, mtdb, name, path, wmax, tsuflist, hsuflist)) err = TRUE; } } cblistclose(files); return err ? FALSE : TRUE; } /* index a file into the database */ int indexfile(ODEUM *odeum, VILLA *mtdb, const char *name, const char *file, int wmax, const CBLIST *tsuflist, const CBLIST *hsuflist){ static int cnt = 0; char *vbuf, *buf, *uri; const char *title; int size, hot, vsiz, wnum, bnum; time_t mtime; ODDOC *doc; if(!cbfilestat(file, NULL, &size, &mtime)){ printferror("%s: file does not exist", file); return FALSE; } hot = TRUE; if((vbuf = vlget(mtdb, file, -1, &vsiz)) != NULL){ if(vsiz == sizeof(int) && mtime <= *(int *)vbuf) hot = FALSE; free(vbuf); } if(!hot){ printfinfo("%s: passed", file); return TRUE; } doc = NULL; uri = filetouri(file); if(bwimatchlist(file, tsuflist)){ if(!(buf = cbreadfile(file, NULL))){ printferror("%s: file cannot be opened", file); return FALSE; } doc = makedocplain(uri, buf, datestr(mtime)); free(buf); } else if(bwimatchlist(file, hsuflist)){ if(!(buf = cbreadfile(file, NULL))){ printferror("%s: file cannot be opened", file); return FALSE; } doc = makedochtml(uri, buf, datestr(mtime)); free(buf); } free(uri); if(doc){ if(!(title = oddocgetattr(doc, "title")) || strlen(title) < 1){ if((title = strrchr(file, PATHCHR)) != NULL){ title++; } else { title = file; } oddocaddattr(doc, "title", title); } if(odput(odeum, doc, wmax, TRUE) && vlput(mtdb, file, -1, (char *)&mtime, sizeof(int), VL_DOVER)){ printfinfo("%s: registered: id=%d wnum=%d", file, oddocid(doc), cblistnum(oddocnwords(doc))); cnt++; } else { pdperror(file); } oddocclose(doc); } wnum = odwnum(odeum); bnum = odbnum(odeum); if(wnum != -1 && bnum != -1 && (double)wnum / (double)bnum > MAXLOAD){ printfinfo("%s: optimizing started: fsiz=%.0f dnum=%d wnum=%d bnum=%d", name, odfsiz(odeum), oddnum(odeum), odwnum(odeum), odbnum(odeum)); if(!odoptimize(odeum)){ pdperror(file); return FALSE; } printfinfo("%s: optimizing completed: fsiz=%.0f dnum=%d wnum=%d bnum=%d", name, odfsiz(odeum), oddnum(odeum), odwnum(odeum), odbnum(odeum)); } if(cnt >= 256){ printfinfo("%s: database status: fsiz=%.0f dnum=%d wnum=%d bnum=%d", name, odfsiz(odeum), oddnum(odeum), odwnum(odeum), odbnum(odeum)); cnt = 0; } return TRUE; } /* make the url from file path */ char *filetouri(const char *file){ CBLIST *list; char str[PATHBUFSIZ], *wp, *enc; const char *name; int i, nsiz; sprintf(str, "%c", PATHCHR); list = cbsplit(file, -1, str); wp = str; for(i = 0; i < cblistnum(list); i++){ if(i > 0) *(wp++) = '/'; name = cblistval(list, i, &nsiz); enc = cburlencode(name, nsiz); wp += sprintf(wp, "%s", enc); free(enc); } cblistclose(list); *wp = '\0'; return cbmemdup(str, -1); } /* make a document of plain text */ ODDOC *makedocplain(const char *uri, const char *text, const char *date){ ODDOC *doc; CBLIST *awords; const char *asis; char *normal; int i; doc = oddocopen(uri); if(date) oddocaddattr(doc, "date", date); awords = odbreaktext(text); for(i = 0; i < cblistnum(awords); i++){ asis = cblistval(awords, i, NULL); normal = odnormalizeword(asis); oddocaddword(doc, normal, asis); free(normal); } cblistclose(awords); return doc; } /* make a document of HTML */ ODDOC *makedochtml(const char *uri, const char *html, const char *date){ ODDOC *doc; CBMAP *pairs; CBLIST *elems, *awords; const char *text, *asis; char *rtext, *normal; int i, j, body; pairs = htmlescpairs(); doc = oddocopen(uri); if(date) oddocaddattr(doc, "date", date); elems = cbxmlbreak(html, TRUE); body = FALSE; for(i = 0; i < cblistnum(elems); i++){ text = cblistval(elems, i, NULL); if(cbstrfwimatch(text, "= 0){ if(rtext[j] != ' ') break; rtext[j] = '\0'; } for(j = 0; rtext[j] != '\0'; j++){ if(rtext[j] != ' ') break; } oddocaddattr(doc, "title", rtext + j); awords = odbreaktext(rtext); for(j = 0; j < cblistnum(awords); j++){ asis = cblistval(awords, j, NULL); normal = odnormalizeword(asis); oddocaddword(doc, normal, ""); free(normal); } cblistclose(awords); free(rtext); } } else if(cbstrfwimatch(text, ">", "(1/4)", "(1/2)", "(3/4)", "?", "A", "A", "A", "A", "A", "A", "AE", "C", "E", "E", "E", "E", "I", "I", "I", "I", "D", "N", "O", "O", "O", "O", "O", "*", "O", "U", "U", "U", "U", "Y", "P", "s", "a", "a", "a", "a", "a", "a", "ae", "c", "e", "e", "e", "e", "i", "i", "i", "i", "o", "n", "o", "o", "o", "o", "o", "/", "o", "u", "u", "u", "u", "y", "p", "y", NULL }; static CBMAP *pairs = NULL; char kbuf[8], vbuf[8]; int i, ksiz, vsiz; if(pairs) return pairs; pairs = cbmapopen(); cbglobalgc(pairs, (void (*)(void *))cbmapclose); cbmapput(pairs, "&", -1, "&", -1, TRUE); cbmapput(pairs, "<", -1, "<", -1, TRUE); cbmapput(pairs, ">", -1, ">", -1, TRUE); cbmapput(pairs, """, -1, "\"", -1, TRUE); cbmapput(pairs, "'", -1, "'", -1, TRUE); cbmapput(pairs, " ", -1, " ", -1, TRUE); cbmapput(pairs, "©", -1, "(C)", -1, TRUE); cbmapput(pairs, "®", -1, "(R)", -1, TRUE); cbmapput(pairs, "™", -1, "(TM)", -1, TRUE); for(i = 1; i <= 127; i++){ ksiz = sprintf(kbuf, "&#%d;", i); vsiz = sprintf(vbuf, "%c", i); cbmapput(pairs, kbuf, ksiz, vbuf, vsiz, TRUE); } cbmapput(pairs, "‚", -1, ",", -1, TRUE); cbmapput(pairs, "„", -1, ",,", -1, TRUE); cbmapput(pairs, "…", -1, "...", -1, TRUE); cbmapput(pairs, "‹", -1, "<", -1, TRUE); cbmapput(pairs, "‘", -1, "'", -1, TRUE); cbmapput(pairs, "’", -1, "'", -1, TRUE); cbmapput(pairs, "“", -1, "\"", -1, TRUE); cbmapput(pairs, "”", -1, "\"", -1, TRUE); cbmapput(pairs, "–", -1, "-", -1, TRUE); cbmapput(pairs, "—", -1, "-", -1, TRUE); cbmapput(pairs, "˜", -1, "~", -1, TRUE); cbmapput(pairs, "™", -1, "(TM)", -1, TRUE); cbmapput(pairs, "›", -1, ">", -1, TRUE); for(i = 0; latinext[i]; i++){ ksiz = sprintf(kbuf, "&#%d;", i + 160); cbmapput(pairs, kbuf, ksiz, latinext[i], -1, TRUE); } return pairs; } /* register scores of documents */ int procrelate(const char *name){ ODEUM *odeum; DEPOT *scdb; ODDOC *doc; CBMAP *scores; const char *file; char path[PATHBUFSIZ], *mbuf; int err, fatal, id, msiz; printfinfo("%s: relating started", name); if(!(odeum = odopen(name, OD_OWRITER))){ pdperror(name); return 1; } sprintf(path, "%s%c%s", name, PATHCHR, SCDBNAME); if(!(scdb = dpopen(path, OD_OWRITER | OD_OCREAT, SCDBBNUM))){ pdperror(name); odclose(odeum); return 1; } if(!dpsetalign(scdb, SCDBALIGN)){ pdperror(name); dpclose(scdb); odclose(odeum); return 1; } printfinfo("%s: database opened: fsiz=%.0f dnum=%d wnum=%d bnum=%d", name, odfsiz(odeum), oddnum(odeum), odwnum(odeum), odbnum(odeum)); err = FALSE; if(!oditerinit(odeum)){ pdperror(name); err = TRUE; } else { while(TRUE){ if(sigterm){ printferror("aborting due to a termination signal"); err = TRUE; break; } if(!(doc = oditernext(odeum))){ if(dpecode != DP_ENOITEM){ pdperror(name); err = TRUE; } break; } file = oddocuri(doc); id = oddocid(doc); scores = oddocscores(doc, KEYNUM, odeum); mbuf = cbmapdump(scores, &msiz); if(!dpput(scdb, (char *)&id, sizeof(int), mbuf, msiz, DP_DOVER)){ pdperror(name); err = TRUE; } else { printfinfo("%s: related", file); } free(mbuf); cbmapclose(scores); oddocclose(doc); if(err) break; } } fatal = odfatalerror(odeum); printfinfo("%s: database closing: fsiz=%.0f dnum=%d wnum=%d bnum=%d", name, odfsiz(odeum), oddnum(odeum), odwnum(odeum), odbnum(odeum)); if(!dpclose(scdb)){ pdperror(name); err = TRUE; } if(!odclose(odeum)){ pdperror(name); err = TRUE; } if(err){ printfinfo("%s: relating was over%s", name, fatal ? " with fatal error" : ""); } else { printfinfo("%s: relating completed successfully", name); } return err ? 1 : 0; } /* purge documents which is not existing. */ int procpurge(const char *name){ ODEUM *odeum; ODDOC *doc; const char *file; int err, fatal; printfinfo("%s: purging started", name); if(!(odeum = odopen(name, OD_OWRITER))){ pdperror(name); return 1; } printfinfo("%s: database opened: fsiz=%.0f dnum=%d wnum=%d bnum=%d", name, odfsiz(odeum), oddnum(odeum), odwnum(odeum), odbnum(odeum)); err = FALSE; if(!oditerinit(odeum)){ pdperror(name); err = TRUE; } else { while(TRUE){ if(sigterm){ printferror("aborting due to a termination signal"); err = TRUE; break; } if(!(doc = oditernext(odeum))){ if(dpecode != DP_ENOITEM){ pdperror(name); err = TRUE; } break; } file = oddocuri(doc); if(cbfilestat(file, NULL, NULL, NULL)){ printfinfo("%s: passed", file); } else { if(!odout(odeum, file)){ pdperror(file); err = TRUE; } printfinfo("%s: purged", file); } oddocclose(doc); } } fatal = odfatalerror(odeum); printfinfo("%s: database closing: fsiz=%.0f dnum=%d wnum=%d bnum=%d", name, odfsiz(odeum), oddnum(odeum), odwnum(odeum), odbnum(odeum)); if(!odclose(odeum)){ pdperror(name); err = TRUE; } if(err){ printfinfo("%s: purging was over%s", name, fatal ? " with fatal error" : ""); } else { printfinfo("%s: purging completed successfully", name); } return err ? 1 : 0; } /* END OF FILE */ qdbm-1.8.78/qmttest.c0000644000175000017500000002072110610630140013402 0ustar mikiomikio/************************************************************************************************* * Test cases for thread-safety * Copyright (C) 2000-2007 Mikio Hirabayashi * This file is part of QDBM, Quick Database Manager. * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU * Lesser General Public License as published by the Free Software Foundation; either version * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * You should have received a copy of the GNU Lesser General Public License along with QDBM; if * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. *************************************************************************************************/ #include #include #include #include #include #include #include #include #include #include #if defined(MYPTHREAD) #include #include #endif #undef TRUE #define TRUE 1 /* boolean true */ #undef FALSE #define FALSE 0 /* boolean false */ #define PATHBUFSIZ 1024 /* buffer for paths */ #define RECBUFSIZ 32 /* buffer for records */ typedef struct { /* type of structure of thread arguments */ int id; /* ID of the thread */ const char *name; /* prefix of the database */ int rnum; /* number of records */ int alive; /* alive or not */ } MYARGS; /* for RISC OS */ #if defined(__riscos__) || defined(__riscos) #include int __riscosify_control = __RISCOSIFY_NO_PROCESS; #endif /* global variables */ const char *progname; /* program name */ /* function prototypes */ int main(int argc, char **argv); void usage(void); void pdperror(const char *name); void *procthread(void *args); int dotest(const char *name, int rnum, int tnum); /* main routine */ int main(int argc, char **argv){ char *env, *name; int rv, rnum, tnum; cbstdiobin(); if((env = getenv("QDBMDBGFD")) != NULL) dpdbgfd = atoi(env); progname = argv[0]; srand(time(NULL)); if(argc < 4) usage(); name = argv[1]; if((rnum = atoi(argv[2])) < 1) usage(); if((tnum = atoi(argv[3])) < 1) usage(); rv = dotest(name, rnum, tnum); return rv; } /* print the usage and exit */ void usage(void){ fprintf(stderr, "%s: test cases for thread-safety\n", progname); fprintf(stderr, "\n"); fprintf(stderr, "usage:\n"); fprintf(stderr, " %s name rnum tnum\n", progname); fprintf(stderr, "\n"); exit(1); } /* print formatted string and flush the buffer */ int printfflush(const char *format, ...){ #if defined(MYPTHREAD) static pthread_mutex_t mymutex = PTHREAD_MUTEX_INITIALIZER; va_list ap; int rv; if(pthread_mutex_lock(&mymutex) != 0) return -1; va_start(ap, format); rv = vprintf(format, ap); if(fflush(stdout) == EOF) rv = -1; va_end(ap); pthread_mutex_unlock(&mymutex); return rv; #else va_list ap; int rv; va_start(ap, format); rv = vprintf(format, ap); if(fflush(stdout) == EOF) rv = -1; va_end(ap); return rv; #endif } /* print an error message */ void pdperror(const char *name){ fprintf(stderr, "%s: %s: %s\n", progname, name, dperrmsg(dpecode)); } /* pseudo random number generator */ int myrand(void){ static int cnt = 0; return (rand() * rand() + (rand() >> (sizeof(int) * 4)) + (cnt++)) & INT_MAX; } /* process the test */ void *procthread(void *args){ MYARGS *myargs; DEPOT *depot; CURIA *curia; VILLA *villa; CBLIST *list; CBMAP *map; char name[PATHBUFSIZ], buf[RECBUFSIZ]; int i, err, len; myargs = (MYARGS *)args; err = FALSE; sprintf(name, "%s-%04d", myargs->name, myargs->id); dpremove(name); crremove(name); vlremove(name); switch(myrand() % 4){ case 0: printfflush("\n[Depot Test] name=%s rnum=%d\n", name, myargs->rnum); if(!(depot = dpopen(name, DP_OWRITER | DP_OCREAT | DP_OTRUNC, -1))){ pdperror(name); return "error"; } for(i = 1; i <= myargs->rnum; i++){ len = sprintf(buf, "%d", myrand() % i + 1); if(!dpput(depot, buf, len, buf, len, i % 2 == 0 ? DP_DOVER : DP_DCAT)){ pdperror(name); err = TRUE; } if(myargs->rnum > 250 && i % (myargs->rnum / 250) == 0){ printfflush("."); if(i == myargs->rnum || i % (myargs->rnum / 10) == 0){ printfflush("\n%s: (%d)\n", name, i); } } } if(!dpclose(depot)){ pdperror(name); err = TRUE; } printfflush("\n%s: finished\n", name); break; case 1: printfflush("\n[Curia Test] name=%s rnum=%d\n", name, myargs->rnum); if(!(curia = cropen(name, CR_OWRITER | CR_OCREAT | CR_OTRUNC, -1, -1))){ pdperror(name); return "error"; } for(i = 1; i <= myargs->rnum; i++){ len = sprintf(buf, "%d", myrand() % i + 1); if(!crput(curia, buf, len, buf, len, i % 2 == 0 ? CR_DOVER : CR_DCAT)){ pdperror(name); err = TRUE; } if(myargs->rnum > 250 && i % (myargs->rnum / 250) == 0){ printfflush("."); if(i == myargs->rnum || i % (myargs->rnum / 10) == 0){ printfflush("\n%s: (%d)\n", name, i); } } } if(!crclose(curia)){ pdperror(name); err = TRUE; } printfflush("\n%s: finished\n", name); break; case 2: printfflush("\n[Villa Test] name=%s rnum=%d\n", name, myargs->rnum); if(!(villa = vlopen(name, VL_OWRITER | VL_OCREAT | VL_OTRUNC, VL_CMPLEX))){ pdperror(name); return "error"; } for(i = 1; i <= myargs->rnum; i++){ len = sprintf(buf, "%d", myrand() % i + 1); if(!vlput(villa, buf, len, buf, len, i % 2 == 0 ? VL_DOVER : VL_DDUP)){ pdperror(name); err = TRUE; } if(myargs->rnum > 250 && i % (myargs->rnum / 250) == 0){ printfflush("."); if(i == myargs->rnum || i % (myargs->rnum / 10) == 0){ printfflush("\n%s: (%d)\n", name, i); } } } if(!vlclose(villa)){ pdperror(name); err = TRUE; } printfflush("\n%s: finished\n", name); break; case 3: printfflush("\n[Cabin Test] name=%s rnum=%d\n", name, myargs->rnum); list = cblistopen(); map = cbmapopen(); for(i = 1; i <= myargs->rnum; i++){ len = sprintf(buf, "%d", myrand() % i + 1); cblistpush(list, buf, len); cbmapput(map, buf, len, buf, len, i % 2 == 0 ? TRUE : FALSE); if(myargs->rnum > 250 && i % (myargs->rnum / 250) == 0){ printfflush("."); if(i == myargs->rnum || i % (myargs->rnum / 10) == 0){ printfflush("\n%s: (%d)\n", name, i); } } } cbmapclose(map); cblistclose(list); printfflush("\n%s: finished\n", name); break; } return err ? "error" : NULL; } /* drive the test */ int dotest(const char *name, int rnum, int tnum){ #if defined(MYPTHREAD) pthread_t *thary; MYARGS *argsary; char *rv; int i, err; printfflush("\n name=%s rnum=%d tnum=%d\n", name, rnum, tnum); err = FALSE; thary = cbmalloc(tnum * sizeof(pthread_t)); argsary = cbmalloc(tnum * sizeof(MYARGS)); for(i = 0; i < tnum; i++){ argsary[i].id = i + 1; argsary[i].name = name; argsary[i].rnum = rnum; argsary[i].alive = TRUE; if(pthread_create(thary + i, NULL, procthread, argsary + i) != 0){ argsary[i].alive = FALSE; err = TRUE; } } for(i = 0; i < tnum; i++){ if(!argsary[i].alive) continue; if(pthread_join(thary[i], (void *)&rv) != 0 || rv) err = TRUE; } free(argsary); free(thary); if(!err) printfflush("\nall ok\n"); return err ? 1 : 0; #else MYARGS *argsary; int i, err; printfflush("\n name=%s rnum=%d tnum=%d\n", name, rnum, tnum); err = FALSE; argsary = cbmalloc(tnum * sizeof(MYARGS)); for(i = 0; i < tnum; i++){ argsary[i].id = i + 1; argsary[i].name = name; argsary[i].rnum = rnum; argsary[i].alive = TRUE; if(procthread(argsary + i)) err = TRUE; } free(argsary); if(!err) printfflush("\nall ok\n"); return err ? 1 : 0; #endif } /* END OF FILE */ qdbm-1.8.78/dpmgr.c0000644000175000017500000005124510610627747013042 0ustar mikiomikio/************************************************************************************************* * Utility for debugging Depot and its applications * Copyright (C) 2000-2007 Mikio Hirabayashi * This file is part of QDBM, Quick Database Manager. * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU * Lesser General Public License as published by the Free Software Foundation; either version * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * You should have received a copy of the GNU Lesser General Public License along with QDBM; if * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. *************************************************************************************************/ #include #include #include #include #include #undef TRUE #define TRUE 1 /* boolean true */ #undef FALSE #define FALSE 0 /* boolean false */ #define ALIGNSIZ 32 /* basic size of alignment */ /* for RISC OS */ #if defined(__riscos__) || defined(__riscos) #include int __riscosify_control = __RISCOSIFY_NO_PROCESS; #endif /* global variables */ const char *progname; /* program name */ /* function prototypes */ int main(int argc, char **argv); void usage(void); char *hextoobj(const char *str, int *sp); char *dectoiobj(const char *str, int *sp); int runcreate(int argc, char **argv); int runput(int argc, char **argv); int runout(int argc, char **argv); int runget(int argc, char **argv); int runlist(int argc, char **argv); int runoptimize(int argc, char **argv); int runinform(int argc, char **argv); int runremove(int argc, char **argv); int runrepair(int argc, char **argv); int runexportdb(int argc, char **argv); int runimportdb(int argc, char **argv); int runsnaffle(int argc, char **argv); void pdperror(const char *name); void printobj(const char *obj, int size); void printobjhex(const char *obj, int size); int docreate(const char *name, int bnum, int sparse); int doput(const char *name, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int dmode, int align); int doout(const char *name, const char *kbuf, int ksiz); int doget(const char *name, int opts, const char *kbuf, int ksiz, int start, int max, int ox, int nb); int dolist(const char *name, int opts, int kb, int vb, int ox); int dooptimize(const char *name, int bnum, int align); int doinform(const char *name, int opts); int doremove(const char *name); int dorepair(const char *name); int doexportdb(const char *name, const char *file); int doimportdb(const char *name, const char *file, int bnum); int dosnaffle(const char *name, const char *kbuf, int ksiz, int ox, int nb); /* main routine */ int main(int argc, char **argv){ char *env; int rv; cbstdiobin(); progname = argv[0]; if((env = getenv("QDBMDBGFD")) != NULL) dpdbgfd = atoi(env); if(argc < 2) usage(); rv = 0; if(!strcmp(argv[1], "create")){ rv = runcreate(argc, argv); } else if(!strcmp(argv[1], "put")){ rv = runput(argc, argv); } else if(!strcmp(argv[1], "out")){ rv = runout(argc, argv); } else if(!strcmp(argv[1], "get")){ rv = runget(argc, argv); } else if(!strcmp(argv[1], "list")){ rv = runlist(argc, argv); } else if(!strcmp(argv[1], "optimize")){ rv = runoptimize(argc, argv); } else if(!strcmp(argv[1], "inform")){ rv = runinform(argc, argv); } else if(!strcmp(argv[1], "remove")){ rv = runremove(argc, argv); } else if(!strcmp(argv[1], "repair")){ rv = runrepair(argc, argv); } else if(!strcmp(argv[1], "exportdb")){ rv = runexportdb(argc, argv); } else if(!strcmp(argv[1], "importdb")){ rv = runimportdb(argc, argv); } else if(!strcmp(argv[1], "snaffle")){ rv = runsnaffle(argc, argv); } else if(!strcmp(argv[1], "version") || !strcmp(argv[1], "--version")){ printf("Powered by QDBM version %s on %s%s\n", dpversion, dpsysname, dpisreentrant ? " (reentrant)" : ""); printf("Copyright (c) 2000-2007 Mikio Hirabayashi\n"); rv = 0; } else { usage(); } return rv; } /* print the usage and exit */ void usage(void){ fprintf(stderr, "%s: administration utility for Depot\n", progname); fprintf(stderr, "\n"); fprintf(stderr, "usage:\n"); fprintf(stderr, " %s create [-s] [-bnum num] name\n", progname); fprintf(stderr, " %s put [-kx|-ki] [-vx|-vi|-vf] [-keep|-cat] [-na] name key val\n", progname); fprintf(stderr, " %s out [-kx|-ki] name key\n", progname); fprintf(stderr, " %s get [-nl] [-kx|-ki] [-start num] [-max num] [-ox] [-n] name key\n", progname); fprintf(stderr, " %s list [-nl] [-k|-v] [-ox] name\n", progname); fprintf(stderr, " %s optimize [-bnum num] [-na] name\n", progname); fprintf(stderr, " %s inform [-nl] name\n", progname); fprintf(stderr, " %s remove name\n", progname); fprintf(stderr, " %s repair name\n", progname); fprintf(stderr, " %s exportdb name file\n", progname); fprintf(stderr, " %s importdb [-bnum num] name file\n", progname); fprintf(stderr, " %s snaffle [-kx|-ki] [-ox] [-n] name key\n", progname); fprintf(stderr, " %s version\n", progname); fprintf(stderr, "\n"); exit(1); } /* create a binary object from a hexadecimal string */ char *hextoobj(const char *str, int *sp){ char *buf, mbuf[3]; int len, i, j; len = strlen(str); if(!(buf = malloc(len + 1))) return NULL; j = 0; for(i = 0; i < len; i += 2){ while(strchr(" \n\r\t\f\v", str[i])){ i++; } if((mbuf[0] = str[i]) == '\0') break; if((mbuf[1] = str[i+1]) == '\0') break; mbuf[2] = '\0'; buf[j++] = (char)strtol(mbuf, NULL, 16); } buf[j] = '\0'; *sp = j; return buf; } /* create a integer object from a decimal string */ char *dectoiobj(const char *str, int *sp){ char *buf; int num; num = atoi(str); if(!(buf = malloc(sizeof(int)))) return NULL; *(int *)buf = num; *sp = sizeof(int); return buf; } /* parse arguments of create command */ int runcreate(int argc, char **argv){ char *name; int i, sb, bnum, rv; name = NULL; sb = FALSE; bnum = -1; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ if(!strcmp(argv[i], "-s")){ sb = TRUE; } else if(!strcmp(argv[i], "-bnum")){ if(++i >= argc) usage(); bnum = atoi(argv[i]); } else { usage(); } } else if(!name){ name = argv[i]; } else { usage(); } } if(!name) usage(); rv = docreate(name, bnum, sb); return rv; } /* parse arguments of put command */ int runput(int argc, char **argv){ char *name, *key, *val, *kbuf, *vbuf; int i, kx, ki, vx, vi, vf, align, ksiz, vsiz, rv; int dmode; name = NULL; kx = FALSE; ki = FALSE; vx = FALSE; vi = FALSE; vf = FALSE; align = ALIGNSIZ; key = NULL; val = NULL; dmode = DP_DOVER; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ if(!strcmp(argv[i], "-kx")){ kx = TRUE; } else if(!strcmp(argv[i], "-ki")){ ki = TRUE; } else if(!strcmp(argv[i], "-vx")){ vx = TRUE; } else if(!strcmp(argv[i], "-vi")){ vi = TRUE; } else if(!strcmp(argv[i], "-vf")){ vf = TRUE; } else if(!strcmp(argv[i], "-keep")){ dmode = DP_DKEEP; } else if(!strcmp(argv[i], "-cat")){ dmode = DP_DCAT; } else if(!strcmp(argv[i], "-na")){ align = 0; } else { usage(); } } else if(!name){ name = argv[i]; } else if(!key){ key = argv[i]; } else if(!val){ val = argv[i]; } else { usage(); } } if(!name || !key || !val) usage(); if(kx){ kbuf = hextoobj(key, &ksiz); } else if(ki){ kbuf = dectoiobj(key, &ksiz); } else { kbuf = cbmemdup(key, -1); ksiz = -1; } if(vx){ vbuf = hextoobj(val, &vsiz); } else if(vi){ vbuf = dectoiobj(val, &vsiz); } else if(vf){ vbuf = cbreadfile(val, &vsiz); } else { vbuf = cbmemdup(val, -1); vsiz = -1; } if(kbuf && vbuf){ rv = doput(name, kbuf, ksiz, vbuf, vsiz, dmode, align); } else { if(vf){ fprintf(stderr, "%s: %s: cannot read\n", progname, val); } else { fprintf(stderr, "%s: out of memory\n", progname); } rv = 1; } free(kbuf); free(vbuf); return rv; } /* parse arguments of out command */ int runout(int argc, char **argv){ char *name, *key, *kbuf; int i, kx, ki, ksiz, rv; name = NULL; kx = FALSE; ki = FALSE; key = NULL; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ if(!strcmp(argv[i], "-kx")){ kx = TRUE; } else if(!strcmp(argv[i], "-ki")){ ki = TRUE; } else { usage(); } } else if(!name){ name = argv[i]; } else if(!key){ key = argv[i]; } else { usage(); } } if(!name || !key) usage(); if(kx){ kbuf = hextoobj(key, &ksiz); } else if(ki){ kbuf = dectoiobj(key, &ksiz); } else { kbuf = cbmemdup(key, -1); ksiz = -1; } if(kbuf){ rv = doout(name, kbuf, ksiz); } else { fprintf(stderr, "%s: out of memory\n", progname); rv = 1; } free(kbuf); return rv; } /* parse arguments of get command */ int runget(int argc, char **argv){ char *name, *key, *kbuf; int i, opts, kx, ki, ox, nb, start, max, ksiz, rv; name = NULL; opts = 0; kx = FALSE; ki = FALSE; ox = FALSE; nb = FALSE; start = 0; max = -1; key = NULL; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ if(!strcmp(argv[i], "-nl")){ opts |= DP_ONOLCK; } else if(!strcmp(argv[i], "-kx")){ kx = TRUE; } else if(!strcmp(argv[i], "-ki")){ ki = TRUE; } else if(!strcmp(argv[i], "-ox")){ ox = TRUE; } else if(!strcmp(argv[i], "-n")){ nb = TRUE; } else if(!strcmp(argv[i], "-start")){ if(++i >= argc) usage(); start = atoi(argv[i]); } else if(!strcmp(argv[i], "-max")){ if(++i >= argc) usage(); max = atoi(argv[i]); } else { usage(); } } else if(!name){ name = argv[i]; } else if(!key){ key = argv[i]; } else { usage(); } } if(!name || !key || start < 0) usage(); if(kx){ kbuf = hextoobj(key, &ksiz); } else if(ki){ kbuf = dectoiobj(key, &ksiz); } else { kbuf = cbmemdup(key, -1); ksiz = -1; } if(kbuf){ rv = doget(name, opts, kbuf, ksiz, start, max, ox, nb); } else { fprintf(stderr, "%s: out of memory\n", progname); rv = 1; } free(kbuf); return rv; } /* parse arguments of list command */ int runlist(int argc, char **argv){ char *name; int i, opts, kb, vb, ox, rv; name = NULL; opts = 0; kb = FALSE; vb = FALSE; ox = FALSE; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ if(!strcmp(argv[i], "-nl")){ opts |= DP_ONOLCK; } else if(!strcmp(argv[i], "-k")){ kb = TRUE; } else if(!strcmp(argv[i], "-v")){ vb = TRUE; } else if(!strcmp(argv[i], "-ox")){ ox = TRUE; } else { usage(); } } else if(!name){ name = argv[i]; } else { usage(); } } if(!name) usage(); rv = dolist(name, opts, kb, vb, ox); return rv; } /* parse arguments of optimize command */ int runoptimize(int argc, char **argv){ char *name; int i, bnum, align, rv; name = NULL; bnum = -1; align = ALIGNSIZ; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ if(!strcmp(argv[i], "-bnum")){ if(++i >= argc) usage(); bnum = atoi(argv[i]); } else if(!strcmp(argv[i], "-na")){ align = 0; } else { usage(); } } else if(!name){ name = argv[i]; } else { usage(); } } if(!name) usage(); rv = dooptimize(name, bnum, align); return rv; } /* parse arguments of inform command */ int runinform(int argc, char **argv){ char *name; int i, opts, rv; name = NULL; opts = 0; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ if(!strcmp(argv[i], "-nl")){ opts |= DP_ONOLCK; } else { usage(); } } else if(!name){ name = argv[i]; } else { usage(); } } if(!name) usage(); rv = doinform(name, opts); return rv; } /* parse arguments of remove command */ int runremove(int argc, char **argv){ char *name; int i, rv; name = NULL; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ usage(); } else if(!name){ name = argv[i]; } else { usage(); } } if(!name) usage(); rv = doremove(name); return rv; } /* parse arguments of repair command */ int runrepair(int argc, char **argv){ char *name; int i, rv; name = NULL; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ usage(); } else if(!name){ name = argv[i]; } else { usage(); } } if(!name) usage(); rv = dorepair(name); return rv; } /* parse arguments of exportdb command */ int runexportdb(int argc, char **argv){ char *name, *file; int i, rv; name = NULL; file = NULL; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ usage(); } else if(!name){ name = argv[i]; } else if(!file){ file = argv[i]; } else { usage(); } } if(!name || !file) usage(); rv = doexportdb(name, file); return rv; } /* parse arguments of importdb command */ int runimportdb(int argc, char **argv){ char *name, *file; int i, bnum, rv; name = NULL; file = NULL; bnum = -1; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ if(!strcmp(argv[i], "-bnum")){ if(++i >= argc) usage(); bnum = atoi(argv[i]); } else { usage(); } } else if(!name){ name = argv[i]; } else if(!file){ file = argv[i]; } else { usage(); } } if(!name || !file) usage(); rv = doimportdb(name, file, bnum); return rv; } /* parse arguments of snaffle command */ int runsnaffle(int argc, char **argv){ char *name, *key, *kbuf; int i, kx, ki, ox, nb, start, max, ksiz, rv; name = NULL; kx = FALSE; ki = FALSE; ox = FALSE; nb = FALSE; start = 0; max = -1; key = NULL; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ if(!strcmp(argv[i], "-kx")){ kx = TRUE; } else if(!strcmp(argv[i], "-ki")){ ki = TRUE; } else if(!strcmp(argv[i], "-ox")){ ox = TRUE; } else if(!strcmp(argv[i], "-n")){ nb = TRUE; } else { usage(); } } else if(!name){ name = argv[i]; } else if(!key){ key = argv[i]; } else { usage(); } } if(!name || !key || start < 0) usage(); if(kx){ kbuf = hextoobj(key, &ksiz); } else if(ki){ kbuf = dectoiobj(key, &ksiz); } else { kbuf = cbmemdup(key, -1); ksiz = -1; } if(kbuf){ rv = dosnaffle(name, kbuf, ksiz, ox, nb); } else { fprintf(stderr, "%s: out of memory\n", progname); rv = 1; } free(kbuf); return rv; } /* print an error message */ void pdperror(const char *name){ fprintf(stderr, "%s: %s: %s\n", progname, name, dperrmsg(dpecode)); } /* print an object */ void printobj(const char *obj, int size){ int i; for(i = 0; i < size; i++){ putchar(obj[i]); } } /* print an object as a hexadecimal string */ void printobjhex(const char *obj, int size){ int i; for(i = 0; i < size; i++){ printf("%s%02X", i > 0 ? " " : "", ((const unsigned char *)obj)[i]); } } /* perform create command */ int docreate(const char *name, int bnum, int sparse){ DEPOT *depot; int omode; omode = DP_OWRITER | DP_OCREAT | DP_OTRUNC | (sparse ? DP_OSPARSE : 0); if(!(depot = dpopen(name, omode, bnum))){ pdperror(name); return 1; } if(!dpclose(depot)){ pdperror(name); return 1; } return 0; } /* perform put command */ int doput(const char *name, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int dmode, int align){ DEPOT *depot; if(!(depot = dpopen(name, DP_OWRITER, -1))){ pdperror(name); return 1; } if(align > 0 && !dpsetalign(depot, align)){ pdperror(name); dpclose(depot); return 1; } if(!dpput(depot, kbuf, ksiz, vbuf, vsiz, dmode)){ pdperror(name); dpclose(depot); return 1; } if(!dpclose(depot)){ pdperror(name); return 1; } return 0; } /* perform out command */ int doout(const char *name, const char *kbuf, int ksiz){ DEPOT *depot; if(!(depot = dpopen(name, DP_OWRITER, -1))){ pdperror(name); return 1; } if(!dpout(depot, kbuf, ksiz)){ pdperror(name); dpclose(depot); return 1; } if(!dpclose(depot)){ pdperror(name); return 1; } return 0; } /* perform get command */ int doget(const char *name, int opts, const char *kbuf, int ksiz, int start, int max, int ox, int nb){ DEPOT *depot; char *vbuf; int vsiz; if(!(depot = dpopen(name, DP_OREADER | opts, -1))){ pdperror(name); return 1; } if(!(vbuf = dpget(depot, kbuf, ksiz, start, max, &vsiz))){ pdperror(name); dpclose(depot); return 1; } if(ox){ printobjhex(vbuf, vsiz); } else { printobj(vbuf, vsiz); } free(vbuf); if(!nb) putchar('\n'); if(!dpclose(depot)){ pdperror(name); return 1; } return 0; } /* perform list command */ int dolist(const char *name, int opts, int kb, int vb, int ox){ DEPOT *depot; char *kbuf, *vbuf; int ksiz, vsiz; if(!(depot = dpopen(name, DP_OREADER | opts, -1))){ pdperror(name); return 1; } dpiterinit(depot); while((kbuf = dpiternext(depot, &ksiz)) != NULL){ if(!(vbuf = dpget(depot, kbuf, ksiz, 0, -1, &vsiz))){ pdperror(name); free(kbuf); break; } if(ox){ if(!vb) printobjhex(kbuf, ksiz); if(!kb && !vb) putchar('\t'); if(!kb) printobjhex(vbuf, vsiz); } else { if(!vb) printobj(kbuf, ksiz); if(!kb && !vb) putchar('\t'); if(!kb) printobj(vbuf, vsiz); } putchar('\n'); free(vbuf); free(kbuf); } if(!dpclose(depot)){ pdperror(name); return 1; } return 0; } /* perform optimize command */ int dooptimize(const char *name, int bnum, int align){ DEPOT *depot; if(!(depot = dpopen(name, DP_OWRITER, -1))){ pdperror(name); return 1; } if(align > 0 && !dpsetalign(depot, align)){ pdperror(name); dpclose(depot); return 1; } if(!dpoptimize(depot, bnum)){ pdperror(name); dpclose(depot); return 1; } if(!dpclose(depot)){ pdperror(name); return 1; } return 0; } /* perform inform command */ int doinform(const char *name, int opts){ DEPOT *depot; char *tmp; if(!(depot = dpopen(name, DP_OREADER | opts, -1))){ pdperror(name); return 1; } tmp = dpname(depot); printf("name: %s\n", tmp ? tmp : "(null)"); free(tmp); printf("file size: %d\n", dpfsiz(depot)); printf("all buckets: %d\n", dpbnum(depot)); printf("used buckets: %d\n", dpbusenum(depot)); printf("records: %d\n", dprnum(depot)); printf("inode number: %d\n", dpinode(depot)); printf("modified time: %.0f\n", (double)dpmtime(depot)); if(!dpclose(depot)){ pdperror(name); return 1; } return 0; } /* perform remove command */ int doremove(const char *name){ if(!dpremove(name)){ pdperror(name); return 1; } return 0; } /* perform repair command */ int dorepair(const char *name){ if(!dprepair(name)){ pdperror(name); return 1; } return 0; } /* perform exportdb command */ int doexportdb(const char *name, const char *file){ DEPOT *depot; if(!(depot = dpopen(name, DP_OREADER, -1))){ pdperror(name); return 1; } if(!dpexportdb(depot, file)){ pdperror(name); dpclose(depot); return 1; } if(!dpclose(depot)){ pdperror(name); return 1; } return 0; } /* perform importdb command */ int doimportdb(const char *name, const char *file, int bnum){ DEPOT *depot; if(!(depot = dpopen(name, DP_OWRITER | DP_OCREAT | DP_OTRUNC, bnum))){ pdperror(name); return 1; } if(!dpimportdb(depot, file)){ pdperror(name); dpclose(depot); return 1; } if(!dpclose(depot)){ pdperror(name); return 1; } return 0; } /* perform snaffle command */ int dosnaffle(const char *name, const char *kbuf, int ksiz, int ox, int nb){ char *vbuf; int vsiz; if(!(vbuf = dpsnaffle(name, kbuf, ksiz, &vsiz))){ pdperror(name); return 1; } if(ox){ printobjhex(vbuf, vsiz); } else { printobj(vbuf, vsiz); } free(vbuf); if(!nb) putchar('\n'); return 0; } /* END OF FILE */ qdbm-1.8.78/cgi/0000755000175000017500000000000011426320070012301 5ustar mikiomikioqdbm-1.8.78/cgi/cgispex.html0000644000175000017500000003273211426311711014642 0ustar mikiomikio Specifications of CGI Scripts of QDBM

Specifications of CGI Scripts of QDBM

Copyright (C) 2000-2006 Mikio Hirabayashi
Last Update: Thu, 26 Oct 2006 15:00:20 +0900

Table of Contents

  1. Overview
  2. Building
  3. CGI Script for Database Administration
  4. CGI Script for File Upload
  5. CGI Script for Full-text Search
  6. Configuration of Web Servers

Overview

Three CGI scripts are included in the package of QDBM, as utilities or sample applications. The first administers databases of Depot, Curia, and Villa. The second helps you to upload files, with utilities of Cabin. The third realizes a full-text search system with a database of Odeum.


Building

Change the current working directory to the sub directory named `cgi'.

cd cgi

Run the configuration script.

./configure

Build programs.

make

Install programs. This operation must be carried out by the root user.

make install

When a series of work finishes, the following files will be installed. As for the rest, documents will be installed under `/usr/local/share/qdbm/cgi'.

/usr/local/libexec/qadm.cgi
/usr/local/libexec/qupl.cgi
/usr/local/libexec/qfts.cgi
/usr/local/share/qdbm/cgi/qadm.conf
/usr/local/share/qdbm/cgi/qupl.conf
/usr/local/share/qdbm/cgi/qfts.conf

Install CGI scripts and their configuration files to a public directory of WWW, according to each of the following sections.


CGI Script for Database Administration

`qadm.cgi' is a CGI script to administer database files of Depot, Curia, and Villa. Database files can be administered with it via WWW. Contents of the key and the value of each record should be character strings. The comparing function of the advanced API is lexical ordering. The available operations are listing databases, creating a database, removing a database, downloading a database, listing records, storing a record and deleting a record.

To install `qadm.cgi', perform the following steps. Copy `qdbm.cgi' and `qadm.conf' into a directory where CGI is available. And, create a directory `qadmdir' in the CGI directory. For example, if the CGI directory is `/home/mikio/public_html', the following steps are suggested.

cd /home/mikio/public_html
cp /usr/local/libexec/qadm.cgi .
cp /usr/local/share/qdbm/cgi/qadm.conf .
mkdir qadmdir

The directory `qadmdir' should be granted the permission of reading, writing, and execution. Being most easily, the following steps are suggested. As for the rest, you can grant the CGI script setuid bit, or you can use a so-called suExec mechanism.

cd /home/mikio/public_html
chmod 1777 qadmdir

`qadm.conf' is the configuration file. As the default contents are the following, you can modify them arbitrarily.

encoding: UTF-8
lang: en
title: Administration CGI
datadir: qadmdir
keychop: true
valchop: false

`encoding' specifies the character encoding of the shown page and the records of database files. `lang' specifies the language of the shown page. `title' specifies the title of the shown page. `datadir' specifies the path of the directory containing database files. `keychop' and `valchop' specifies whether to normalize keys or values. If one is `true', white spaces at the end of each content are removed, and the contents can not contain linefeed codes.

Access the URL of `qadm.cgi' with a web browser. Then, follow the navigation of the page and administer the database.

For automatic agents to retrieve a stored record, the mechanism to get the as-is contents of the value of a records specified with a URL is provided. For example, if the URL of the CGI script is `http://a.b.c/qadm.cgi' and the name of the database is `staff' and the key is `mikio', the agent should access `http://a.b.c/qadm.cgi/staff/mikio'. That is, separated with '/', the URL of the CGI script entails the database name (without any suffix), which entails the key.

If you want to administer existing database files, you should place them in the directory `qadmdir'. And, the database files of the basic API should have the suffix `.dp'. The database directories of the extended API should have the suffix `.cr'. The database files of the advanced API should have the suffix `.vl'. For example, they are `foo.dp', `bar.cr' or `baz.vl'. Moreover, each database file or directory should be writable and readable by the CGI script.


CGI Script for File Upload

`qupl.cgi' is a CGI script to upload files, with Cabin. You can upload arbitrary files to your web server. You can perform downloading and deleting also.

To install `qupl.cgi', perform the following steps. Copy `qupl.cgi' and `qupl.conf' into a directory where CGI is available. And, create a directory `qupldir' in the CGI directory. For example, if the CGI directory is `/home/mikio/public_html', the following steps are suggested.

cd /home/mikio/public_html
cp /usr/local/libexec/qupl.cgi .
cp /usr/local/share/qdbm/cgi/qupl.conf .
mkdir qupldir

The directory `qupldir' should be granted the permission of reading, writing, and execution. Being most easily, the following steps are suggested. As for the rest, you can grant the CGI script setuid bit, or you can use a so-called suExec mechanism.

cd /home/mikio/public_html
chmod 1777 qupldir

`qupl.conf' is the configuration file. As the default contents are the following, you can modify them arbitrarily.

encoding: UTF-8
lang: en
title: Administration CGI
datadir: qupldir
quota: 67108864

`encoding' specifies the character encoding of the shown page and the records of database files. `lang' specifies the language of the shown page. `title' specifies the title of the shown page. `datadir' specifies the path of the directory containing database files. `quota' specifies the limit of the total size of uploaded files.

Access the URL of `qupl.cgi' with a web browser. Then, follow the navigation of the page and administer the files.


CGI Script for Full-text Search

`qfts.cgi' is a CGI script to perform full-text search with a database of Odeum. It realizes full-text search system of a web site. Generating a database of the index is performed with the command `odidx'. Searching the index is performed with `qfts.cgi'. Search methods have two kinds: `AND search' retrieves documents which include all search words, `OR search' retrieves documents which include at least one of search words. Search results are ordered by scores.

To install `qfts.cgi', perform the following steps. Copy `qfts.cgi' and `qfts.conf' into a directory where CGI is available. And, create an index `casket' in the CGI directory. For example, if the CGI directory is `/home/mikio/public_html', the following steps are suggested.

cd /home/mikio/public_html
cp /usr/local/libexec/qfts.cgi .
cp /usr/local/share/qdbm/cgi/qfts.conf .
odidx register casket
odidx relate casket

If directories of search targets are not under the directory including CGI scripts, you can make symbolic links to the target directories there.

When your site is updated, the index also shuld be updated with the following steps. These operations are suggested to be automated with `crontab' and so on.

cd /home/mikio/public_html
odidx register casket
odidx purge casket
odidx relate casket
odmgr optimize casket

`qfts.conf' is the configuration file. As the default contents are the following, you can modify them arbitrarily.

encoding: ISO-8859-1
lang: en
title: Full-text Search CGI
index: casket
prefix: ./
diridx: index.html
decuri: false
help: <h1>Full-text Search CGI</h1>
help: <p>Input search words into the above form and push the [Search] button.</p>
help: <p>This is a sample application of the inverted API of QDBM.</p>

`encoding' specifies the character encoding of the shown page and the records of database files. `lang' specifies the language of the shown page. `title' specifies the title of the shown page. `index' specifies the path of the index. `prefix' specifies the prefix to be attached on the URI of each document. For example, if `prefix' is `http://x.y.z/foo/', `./bar/baz.html' and `bar/baz.html' are shown as `http://x.y.z/foo/bar/baz'. `diridx' specifies the name of a file standing for a directory. For example, if `diridx' is `index.html', `./foo/index.html' is shown as `./foo/'. `decuri' specifies that, if the value is `true', URIs of documents are expressed with decoded. `help' specifies the help message shown at the first page.

Access the URL of `qfts.cgi' with a web browser. Then, follow the navigation of the page and perform full-text search.

For more information about the command `odidx' to generate the index, refer to the fundamental specifications of QDBM. If your site is large-sized, to reduce size of the index, you should consider building QDBM with ZLIB enabled.


Configuration of Web Servers

To use CGI scripts, configuration of your web server should permit CGI execution. If CGI scripts are deployed with usual contents, configuration of Apache is like the following.

Options ExecCGI
AddHandler cgi-script .cgi

Altanatively, if you set up an exclusive directory for CGI scripts, configuration of Apache is like the following.

ScriptAlias /~mikio/cgi-bin/ "/home/mikio/public_html/cgi-bin"

If the library path of your web server does not contain `/usr/local/lib', you may have to define it explicitly. Configuration of Apache is like the following.

SetEnv LD_LIBRARY_PATH "/lib:/usr/lib:/usr/local/lib"

On Microsoft IIS, the directory including a CGI script and the current directory on runtime are defferent. Since the latter is the root of a virtual directory, each configuration file should be deployed there.


qdbm-1.8.78/cgi/qadmdir/0000755000175000017500000000000010106026754013730 5ustar mikiomikioqdbm-1.8.78/cgi/qupldir/0000755000175000017500000000000010112550536013764 5ustar mikiomikioqdbm-1.8.78/cgi/qfts.conf0000644000175000017500000000046107764013473014146 0ustar mikiomikioencoding: ISO-8859-1 lang: en title: Full-text Search CGI index: casket prefix: ./ diridx: index.html decuri: false help:

Full-text Search CGI

help:

Input search words into the above form and push the [Search] button.

help:

This is a sample application of the inverted API of QDBM.

qdbm-1.8.78/cgi/Makefile.in0000644000175000017500000000615710473212447014370 0ustar mikiomikio# Makefile for CGI scripts for QDBM #================================================================ # Setting variables #================================================================ # Generic settings SHELL = @SHELL@ srcdir = @srcdir@ VPATH = @srcdir@ # Packaging PACKAGE = qdbm # Targets MYCGIS = qadm.cgi qupl.cgi qfts.cgi MYCONFS = qadm.conf qupl.conf qfts.conf MYDOCS = cgispex.html cgispex-ja.html # Building binaries CC = gcc CPPFLAGS = -I$(srcdir) -I$(srcdir)/.. -I$(HOME)/include -I/usr/local/include \ -D_XOPEN_SOURCE_EXTENDED=1 -D_GNU_SOURCE=1 -D__EXTENSIONS__=1 -D_HPUX_SOURCE=1 \ -D_POSIX_MAPPED_FILES=1 -D_POSIX_SYNCHRONIZED_IO=1 -DNDEBUG CFLAGS = -Wall -ansi -pedantic -fsigned-char -O2 LIBS = -lqdbm @LIBS@ LDFLAGS = -L$(srcdir)/.. -L$(HOME)/lib -L/usr/local/lib $(LIBS) LDENV = LD_RUN_PATH=/lib:/usr/lib:$(HOME)/lib:/usr/local/lib:$(prefix)/lib # Install destinations prefix = @prefix@ exec_prefix = @exec_prefix@ MYLIBEXECDIR = @libexecdir@ MYDATADIR = @datadir@/$(PACKAGE)/cgi DESTDIR = #================================================================ # Suffix rules #================================================================ .SUFFIXES : .SUFFIXES : .c .o .c.o : $(CC) -c $(CPPFLAGS) $(CFLAGS) $< #================================================================ # Actions #================================================================ targets : @TARGETS@ all : $(MYCGIS) @printf '\n' @printf '#================================================================\n' @printf '# Ready to install.\n' @printf '#================================================================\n' static : make LDFLAGS="-static $(LDFLAGS)" all debug : make CFLAGS="$(CFLAGS) -g" LDFLAGS="-static $(LDFLAGS)" all devel : make CFLAGS="$(CFLAGS) -g -pipe" all sync ; sync clean : rm -rf $(MYCGIS) *.o leak.log *~ install : mkdir -p $(DESTDIR)$(MYLIBEXECDIR) cp -Rf $(MYCGIS) $(DESTDIR)$(MYLIBEXECDIR) mkdir -p $(DESTDIR)$(MYDATADIR) cp -Rf $(MYCONFS) $(MYDOCS) $(DESTDIR)$(MYDATADIR) @printf '\n' @printf '#================================================================\n' @printf '# Thanks for using CGI scripts of QDBM.\n' @printf '#================================================================\n' install-strip : make DESTDIR=$(DESTDIR) install cd $(DESTDIR)$(MYLIBEXECDIR) && strip $(MYCGIS) uninstall : cd $(DESTDIR)$(MYLIBEXECDIR) && rm -f $(MYCGIS) rm -rf $(DESTDIR)$(MYDATADIR) dist : autoconf make distclean distclean : clean rm -rf Makefile config.cache config.log config.status autom4te.cache \ qadmdir/* qupldir/* casket mingw : make CC="gcc -mno-cygwin" MYLIBS="libqdbm.dll.a" \ CFLAGS="-Wall -fsigned-char -O0 -DNDEBUG" \ LDFLAGS="-L$(srcdir)/.. -L/usr/local/lib -lqdbm" .PHONY : all clean #================================================================ # Building binaries #================================================================ qadm.cgi : qadm.o $(LDENV) $(CC) $(CFLAGS) -o $@ qadm.o $(LDFLAGS) qupl.cgi : qupl.o $(LDENV) $(CC) $(CFLAGS) -o $@ qupl.o $(LDFLAGS) qfts.cgi : qfts.o $(LDENV) $(CC) $(CFLAGS) -o $@ qfts.o $(LDFLAGS) # END OF FILE qdbm-1.8.78/cgi/qadm.conf0000644000175000017500000000014110105736343014075 0ustar mikiomikioencoding: UTF-8 lang: en title: Administration CGI datadir: qadmdir keychop: true valchop: false qdbm-1.8.78/cgi/qadm.c0000644000175000017500000010506110355663556013415 0ustar mikiomikio/************************************************************************************************* * CGI script for administration of database files * Copyright (C) 2000-2003 Mikio Hirabayashi * This file is part of QDBM, Quick Database Manager. * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU * Lesser General Public License as published by the Free Software Foundation; either version * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * You should have received a copy of the GNU Lesser General Public License along with QDBM; if * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. *************************************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #undef TRUE #define TRUE 1 /* boolean true */ #undef FALSE #define FALSE 0 /* boolean false */ #define CONFFILE "qadm.conf" /* name of the configuration file */ #define DEFENC "US-ASCII" /* default encoding */ #define DEFLANG "en" /* default language */ #define DEFTITLE "QDBM on WWW" /* default title */ #define DEFDATADIR "qadmdir" /* directory containing database files */ #define RDATAMAX 262144 /* max size of data to read */ #define DBNAMEMAX 128 /* max size of the name of a database */ #define PATHBUFSIZ 1024 /* size of a buffer for path string */ #define TSTRBUFSIZ 256 /* size of a buffer for time string */ enum { ACTNONE, ACTDBDOWN, ACTDBCREATE, ACTDBREMOVE, ACTRECLIST, ACTRECPUTOVER, ACTRECPUTKEEP, ACTRECPUTCAT, ACTRECPUTDUP, ACTRECOUTONE, ACTRECOUTLIST }; enum { DBTDEPOT, DBTCURIA, DBTVILLA, DBTERROR }; /* global variables */ const char *scriptname; /* name of the script */ const char *enc; /* encoding of the page */ const char *lang; /* language of the page */ const char *title; /* title of the page */ int keychop; /* whether to chop keys */ int valchop; /* whether to chop values */ /* function prototypes */ int main(int argc, char **argv); const char *skiplabel(const char *str); CBMAP *getparams(void); char *getpathinfo(void); void senderror(int code, const char *tag, const char *message); void dodbdown(const char *dbname); void dorecdown(const char *dbname, const char *tkey); void htmlprintf(const char *format, ...); void printmime(void); void printdecl(void); void printhead(void); const char *getdbattrs(const char *dbname, int *dbtp, int *rnump, int *fsizp, time_t *mtp); const char *dbtstr(int dbt); const char *timestr(time_t t); void dodblist(); void dodbcreate(const char *dbname, int dbt); void dodbremove(const char *dbname, int sure); void doreclist(const char *dbname, int act, const char *key, const char *val, int sure); void strchop(char *str); void updatedepot(const char *dbname, int act, const char *key, const char *val); void updatecuria(const char *dbname, int act, const char *key, const char *val); void updatevilla(const char *dbname, int act, const char *key, const char *val); void depotreclist(const char *dbname); void curiareclist(const char *dbname); void villareclist(const char *dbname); /* main routine */ int main(int argc, char **argv){ CBMAP *params; CBLIST *lines; const char *tmp, *datadir, *dbname, *key, *val; char *pinfo, *tkey; int i, act, sure, dbt; /* set configurations */ cbstdiobin(); scriptname = argv[0]; if((tmp = getenv("SCRIPT_NAME")) != NULL) scriptname = tmp; enc = NULL; lang = NULL; title = NULL; datadir = NULL; keychop = FALSE; valchop = FALSE; if((lines = cbreadlines(CONFFILE)) != NULL){ for(i = 0; i < cblistnum(lines); i++){ tmp = cblistval(lines, i, NULL); if(cbstrfwmatch(tmp, "encoding:")){ enc = skiplabel(tmp); } else if(cbstrfwmatch(tmp, "lang:")){ lang = skiplabel(tmp); } else if(cbstrfwmatch(tmp, "title:")){ title = skiplabel(tmp); } else if(cbstrfwmatch(tmp, "datadir:")){ datadir = skiplabel(tmp); } else if(cbstrfwmatch(tmp, "keychop:")){ if(!strcmp(skiplabel(tmp), "true")) keychop = TRUE; } else if(cbstrfwmatch(tmp, "valchop:")){ if(!strcmp(skiplabel(tmp), "true")) valchop = TRUE; } } } if(!enc) enc = DEFENC; if(!lang) lang = DEFLANG; if(!title) title = DEFTITLE; if(!datadir) datadir = DEFDATADIR; /* read parameters */ dbname = NULL; act = ACTNONE; sure = FALSE; dbt = DBTERROR; key = NULL; val = NULL; params = getparams(); if((tmp = cbmapget(params, "act", -1, NULL)) != NULL) act = atoi(tmp); if((tmp = cbmapget(params, "sure", -1, NULL)) != NULL) sure = atoi(tmp); if((tmp = cbmapget(params, "dbname", -1, NULL)) != NULL) dbname = tmp; if((tmp = cbmapget(params, "dbt", -1, NULL)) != NULL) dbt = atoi(tmp); if((tmp = cbmapget(params, "key", -1, NULL)) != NULL) key = tmp; if((tmp = cbmapget(params, "val", -1, NULL)) != NULL) val = tmp; if(dbname && strlen(dbname) > DBNAMEMAX) dbname = NULL; pinfo = getpathinfo(); /* show page or send data */ if(chdir(datadir) == -1){ senderror(500, "Internal Server Error", "Could not change the current directory."); } else if(act == ACTDBDOWN){ dodbdown(dbname); } else if(pinfo && (tkey = strchr(pinfo + 1, '/')) != NULL){ dbname = pinfo + 1; *tkey = '\0'; tkey++; dorecdown(dbname, tkey); } else { printmime(); printdecl(); htmlprintf("\n", lang, lang); printhead(); htmlprintf("\n"); if(act == ACTNONE){ htmlprintf("

%@

\n", title); } else { htmlprintf("\n", scriptname); } htmlprintf("
\n"); switch(act){ case ACTDBCREATE: dodbcreate(dbname, dbt); break; case ACTDBREMOVE: dodbremove(dbname, sure); break; case ACTRECLIST: case ACTRECPUTOVER: case ACTRECPUTKEEP: case ACTRECPUTCAT: case ACTRECPUTDUP: case ACTRECOUTONE: case ACTRECOUTLIST: doreclist(dbname, act, key, val, sure); break; default: dodblist(); break; } htmlprintf("
\n"); if(act == ACTNONE) htmlprintf("
Powered by QDBM %@.
\n", dpversion); htmlprintf("\n"); htmlprintf("\n"); } /* release resources */ cbmapclose(params); if(lines) cblistclose(lines); return 0; } /* skip the label of a line */ const char *skiplabel(const char *str){ if(!(str = strchr(str, ':'))) return str; str++; while(*str != '\0' && (*str == ' ' || *str == '\t')){ str++; } return str; } /* get a map of the CGI parameters */ CBMAP *getparams(void){ CBMAP *params; CBLIST *pairs; char *rbuf, *buf, *key, *val, *dkey, *dval; const char *tmp; int i, len, c; params = cbmapopen(); rbuf = NULL; buf = NULL; if((tmp = getenv("CONTENT_LENGTH")) != NULL && (len = atoi(tmp)) > 0 && len <= RDATAMAX){ rbuf = cbmalloc(len + 1); for(i = 0; i < len && (c = getchar()) != EOF; i++){ rbuf[i] = c; } rbuf[i] = '\0'; if(i == len) buf = rbuf; } else { buf = getenv("QUERY_STRING"); } if(buf != NULL){ buf = cbmemdup(buf, -1); pairs = cbsplit(buf, -1, "&"); for(i = 0; i < cblistnum(pairs); i++){ key = cbmemdup(cblistval(pairs, i, NULL), -1); if((val = strchr(key, '=')) != NULL){ *(val++) = '\0'; dkey = cburldecode(key, NULL); dval = cburldecode(val, NULL); cbmapput(params, dkey, -1, dval, -1, FALSE); free(dval); free(dkey); } free(key); } cblistclose(pairs); free(buf); } free(rbuf); return params; } /* get a string for PATH_INFO */ char *getpathinfo(void){ const char *tmp; if((tmp = getenv("PATH_INFO")) != NULL){ return cburldecode(tmp, NULL); } return NULL; } /* send error status */ void senderror(int code, const char *tag, const char *message){ printf("Status: %d %s\r\n", code, tag); printf("Content-Type: text/plain; charset=US-ASCII\r\n"); printf("\r\n"); printf("%s\n", message); } /* send a database */ void dodbdown(const char *dbname){ FILE *ifp; int c; if(!dbname || dbname[0] == '/' || strstr(dbname, "..") || !(ifp = fopen(dbname, "rb"))){ senderror(404, "File Not Found", "The database file was not found."); } else { printf("Content-Type: application/x-qdbm\r\n"); printf("\r\n"); while((c = fgetc(ifp)) != EOF){ putchar(c); } fclose(ifp); } } /* send the value of a record */ void dorecdown(const char *dbname, const char *tkey){ char vlpath[PATHBUFSIZ], crpath[PATHBUFSIZ], dppath[PATHBUFSIZ], *vbuf; int vsiz; DEPOT *depot; CURIA *curia; VILLA *villa; vbuf = NULL; vsiz = 0; sprintf(vlpath, "%s.vl", dbname); sprintf(crpath, "%s.cr", dbname); sprintf(dppath, "%s.dp", dbname); if((villa = vlopen(vlpath, VL_OREADER, VL_CMPLEX)) != NULL){ vbuf = vlget(villa, tkey, -1, &vsiz); vlclose(villa); } else if((curia = cropen(crpath, CR_OREADER, -1, -1)) != NULL){ vbuf = crget(curia, tkey, -1, 0, -1, &vsiz); crclose(curia); } else if((depot = dpopen(dppath, DP_OREADER, -1)) != NULL){ vbuf = dpget(depot, tkey, -1, 0, -1, &vsiz); dpclose(depot); } if(vbuf){ printf("Content-Type: text/plain; charset=%s\r\n", enc); printf("Content-Length: %d\r\n", vsiz); printf("\r\n"); printf("%s", vbuf); free(vbuf); } else { senderror(404, "Record Not Found", "There is no corresponding record."); } } /* HTML-oriented printf */ void htmlprintf(const char *format, ...){ va_list ap; char *tmp; unsigned char c; va_start(ap, format); while(*format != '\0'){ if(*format == '%'){ format++; switch(*format){ case 's': tmp = va_arg(ap, char *); if(!tmp) tmp = "(null)"; printf("%s", tmp); break; case 'd': printf("%d", va_arg(ap, int)); break; case '@': tmp = va_arg(ap, char *); if(!tmp) tmp = "(null)"; while(*tmp){ switch(*tmp){ case '&': printf("&"); break; case '<': printf("<"); break; case '>': printf(">"); break; case '"': printf("""); break; default: putchar(*tmp); break; } tmp++; } break; case '?': tmp = va_arg(ap, char *); if(!tmp) tmp = "(null)"; while(*tmp){ c = *(unsigned char *)tmp; if((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || (c != '\0' && strchr("_-.", c))){ putchar(c); } else if(c == ' '){ putchar('+'); } else { printf("%%%02X", c); } tmp++; } break; case '%': putchar('%'); break; } } else { putchar(*format); } format++; } va_end(ap); } /* print mime headers */ void printmime(void){ printf("Content-Type: text/html; charset=%s\r\n", enc); printf("Cache-Control: no-cache, must-revalidate\r\n"); printf("Pragma: no-cache\r\n"); printf("\r\n"); fflush(stdout); } /* print the declarations of XHTML */ void printdecl(void){ htmlprintf("\n", enc); htmlprintf("\n"); } /* print headers */ void printhead(void){ htmlprintf("\n"); htmlprintf("\n", enc); htmlprintf("\n"); htmlprintf("\n"); htmlprintf("%@\n", title); htmlprintf("\n"); htmlprintf("\n"); } /* get the attributes of a database */ const char *getdbattrs(const char *dbname, int *dbtp, int *rnump, int *fsizp, time_t *mtp){ static char name[PATHBUFSIZ], *tmp; DEPOT *depot; CURIA *curia; VILLA *villa; struct stat sbuf; strcpy(name, dbname); *dbtp = DBTERROR; *fsizp = -1; *rnump = -1; *mtp = -1; if((tmp = strrchr(name, '.')) != NULL){ *tmp = '\0'; tmp++; if(!strcmp(tmp, "dp")){ *dbtp = DBTDEPOT; } else if(!strcmp(tmp, "cr")){ *dbtp = DBTCURIA; } else if(!strcmp(tmp, "vl")){ *dbtp = DBTVILLA; } } switch(*dbtp){ case DBTDEPOT: if((depot = dpopen(dbname, DP_OREADER, -1)) != NULL){ *fsizp = dpfsiz(depot); *rnump = dprnum(depot); dpclose(depot); } break; case DBTCURIA: if((curia = cropen(dbname, CR_OREADER, -1, -1)) != NULL){ *fsizp = crfsiz(curia); *rnump = crrnum(curia); crclose(curia); } break; case DBTVILLA: if((villa = vlopen(dbname, VL_OREADER, VL_CMPLEX)) != NULL){ *fsizp = vlfsiz(villa); *rnump = vlrnum(villa); vlclose(villa); } break; default: break; } if(stat(dbname, &sbuf) == 0){ *mtp = sbuf.st_mtime; } return name; } /* get the string of a database type */ const char *dbtstr(int dbt){ switch(dbt){ case DBTDEPOT: return "Depot"; case DBTCURIA: return "Curia"; case DBTVILLA: return "Villa"; default: break; } return "ERROR"; } /* get the string of the time */ const char *timestr(time_t t){ static char str[TSTRBUFSIZ]; struct tm *tsp; tsp = localtime(&t); sprintf(str, "%04d/%02d/%02d %02d:%02d:%02d", tsp->tm_year + 1900, tsp->tm_mon + 1, tsp->tm_mday, tsp->tm_hour, tsp->tm_min, tsp->tm_sec); return str; } /* list existing databases */ void dodblist(){ CBLIST *files; const char *tmp, *name; int i, dbt, rnum, fsiz; time_t mt; if(!(files = cbdirlist("."))){ htmlprintf("

The data directory could not be scanned.

\n"); return; } cblistsort(files); htmlprintf("

The following are existing database files." " Select a database file and its action.

\n"); htmlprintf("
\n", scriptname); htmlprintf("\n"); htmlprintf("\n"); htmlprintf("\n"); htmlprintf("\n"); htmlprintf("\n"); htmlprintf("\n"); htmlprintf("\n"); htmlprintf("\n"); htmlprintf("\n"); for(i = 0; i < cblistnum(files); i++){ tmp = cblistval(files, i, NULL); if(!strcmp(tmp, ".") || !strcmp(tmp, "..")) continue; name = getdbattrs(tmp, &dbt, &rnum, &fsiz, &mt); htmlprintf("\n"); htmlprintf("\n", name); htmlprintf("\n", dbtstr(dbt)); htmlprintf("\n", fsiz); htmlprintf("\n", rnum); htmlprintf("\n", timestr(mt)); htmlprintf("\n"); htmlprintf("\n"); } htmlprintf("
NameType of DatabaseSizeRecordsLast ModifiedActions
%@%@%d%d%s"); htmlprintf("[OPEN]", scriptname, ACTRECLIST, tmp); htmlprintf(" [REMOVE]", scriptname, ACTDBREMOVE, tmp); if(dbt != DBTCURIA){ htmlprintf(" [D/L]", scriptname, ACTDBDOWN, tmp); } htmlprintf("
\n"); htmlprintf("
\n"); htmlprintf("
\n"); htmlprintf("

This form is used in order to create a new database.

\n"); htmlprintf("
\n", scriptname); htmlprintf("\n"); htmlprintf("\n"); htmlprintf("\n"); htmlprintf("\n"); htmlprintf("\n"); htmlprintf("\n"); htmlprintf("\n"); htmlprintf("\n"); htmlprintf("\n"); htmlprintf("\n"); htmlprintf("\n"); htmlprintf("
NameType of DatabaseAction
" "
\n"); htmlprintf("
\n", ACTDBCREATE); htmlprintf("
\n"); cblistclose(files); } /* create a new database */ void dodbcreate(const char *dbname, int dbt){ CBLIST *files; char path[PATHBUFSIZ]; int i, err; DEPOT *depot; CURIA *curia; VILLA *villa; if(!dbname || strlen(dbname) < 1){ htmlprintf("

The name of the database is not defined.

\n"); return; } if(strchr(dbname, '/')){ htmlprintf("

The name of the database includes invalid characters: `/'.

\n"); return; } if(dbt == DBTERROR){ htmlprintf("

The parameters are invalid.

\n"); return; } if(!(files = cbdirlist("."))){ htmlprintf("

The data directory could not be scanned.

\n"); return; } for(i = 0; i < cblistnum(files); i++){ sprintf(path, "%s.dp", dbname); if(cbstrfwmatch(cblistval(files, i, NULL), path)){ cblistclose(files); htmlprintf("

`%@' is duplicated.

\n", dbname); return; } sprintf(path, "%s.cr", dbname); if(cbstrfwmatch(cblistval(files, i, NULL), path)){ cblistclose(files); htmlprintf("

`%@' is duplicated.

\n", dbname); return; } sprintf(path, "%s.vl", dbname); if(cbstrfwmatch(cblistval(files, i, NULL), path)){ cblistclose(files); htmlprintf("

`%@' is duplicated.

\n", dbname); return; } } cblistclose(files); sprintf(path, "%s.%s", dbname, dbt == DBTDEPOT ? "dp" : dbt == DBTCURIA ? "cr" : "vl"); err = FALSE; switch(dbt){ case DBTDEPOT: if(!(depot = dpopen(path, DP_OWRITER | DP_OCREAT | DP_OTRUNC, -1)) || !dpclose(depot)) err = TRUE; break; case DBTCURIA: if(!(curia = cropen(path, CR_OWRITER | CR_OCREAT | CR_OTRUNC, -1, -1)) || !crclose(curia)) err = TRUE; break; case DBTVILLA: if(!(villa = vlopen(path, VL_OWRITER | VL_OCREAT | VL_OTRUNC, VL_CMPLEX)) || !vlclose(villa)) err = TRUE; break; } if(err){ htmlprintf("

`%@' could not be created.

\n", dbname); } else { htmlprintf("

`%@' was created successfully.

\n", dbname); } } /* remove a database */ void dodbremove(const char *dbname, int sure){ const char *name; int dbt, rnum, fsiz, err; time_t mt; if(!dbname || strlen(dbname) < 1){ htmlprintf("

The name of the database is not defined.

\n"); return; } name = getdbattrs(dbname, &dbt, &rnum, &fsiz, &mt); if(!sure){ htmlprintf("

Do you really remove `%@'?

\n", name); htmlprintf("\n", scriptname, ACTDBREMOVE, dbname); return; } err = FALSE; switch(dbt){ case DBTDEPOT: if(!dpremove(dbname)) err = TRUE; break; case DBTCURIA: if(!crremove(dbname)) err = TRUE; break; case DBTVILLA: if(!vlremove(dbname)) err = TRUE; break; default: err = TRUE; break; } if(err){ htmlprintf("

`%@' could not be removed.

\n", name); } else { htmlprintf("

`%@' was removed successfully.

\n", name); } } /* open a database */ void doreclist(const char *dbname, int act, const char *key, const char *val, int sure){ const char *name; int dbt, rnum, fsiz; time_t mt; if(!dbname || strlen(dbname) < 1){ htmlprintf("

The name of the database is not defined.

\n"); return; } if(strchr(dbname, '/')){ htmlprintf("

The name of the database includes invalid characters: `/'.

\n"); return; } name = getdbattrs(dbname, &dbt, &rnum, &fsiz, &mt); switch(dbt){ case DBTDEPOT: updatedepot(dbname, act, key, val); break; case DBTCURIA: updatecuria(dbname, act, key, val); break; case DBTVILLA: updatevilla(dbname, act, key, val); break; default: htmlprintf("

The type of the database is invalid.

\n"); break; } name = getdbattrs(dbname, &dbt, &rnum, &fsiz, &mt); htmlprintf("\n"); htmlprintf("\n"); htmlprintf("\n"); htmlprintf("\n"); htmlprintf("\n"); htmlprintf("\n"); htmlprintf("\n"); htmlprintf("\n"); htmlprintf("\n"); htmlprintf("\n"); htmlprintf("\n", name); htmlprintf("\n", dbtstr(dbt)); htmlprintf("\n", fsiz); htmlprintf("\n", rnum); htmlprintf("\n", timestr(mt)); htmlprintf("\n"); htmlprintf("\n"); htmlprintf("
NameType of DatabaseSizeRecordsLast ModifiedActions
%@%s%d%d%s"); htmlprintf(" [REMOVE]", scriptname, ACTDBREMOVE, dbname); if(dbt != DBTCURIA){ htmlprintf(" [D/L]", scriptname, ACTDBDOWN, dbname); } htmlprintf("
\n"); htmlprintf("
\n"); htmlprintf("

This form is used in order to update the database.

\n"); htmlprintf("
\n", scriptname); htmlprintf("\n"); htmlprintf("\n"); htmlprintf("\n"); htmlprintf("\n"); htmlprintf("\n"); htmlprintf("\n"); htmlprintf("\n"); htmlprintf("\n"); htmlprintf("\n"); htmlprintf("\n"); htmlprintf("\n"); htmlprintf("\n"); htmlprintf("\n"); htmlprintf("
Action:\n"); htmlprintf("\n"); htmlprintf("\n"); htmlprintf("\n"); htmlprintf("
Key:\n"); if(keychop){ htmlprintf("\n"); } else { htmlprintf("\n"); } htmlprintf("
Value:\n"); if(valchop){ htmlprintf("\n"); } else { htmlprintf("\n"); } htmlprintf("
\n"); htmlprintf("
\n", dbname); htmlprintf("
\n", sure); htmlprintf("
\n"); htmlprintf("
\n"); if(sure){ htmlprintf("

The following are all records of the database." " : " "[HIDE RECORDS]

\n", scriptname, ACTRECLIST); switch(dbt){ case DBTDEPOT: depotreclist(dbname); break; case DBTCURIA: curiareclist(dbname); break; case DBTVILLA: villareclist(dbname); break; default: break; } } else { htmlprintf("

The records are not shown now." " : " "[SHOW RECORDS]

\n", scriptname, ACTRECLIST); } } /* chop the string */ void strchop(char *str){ int i; for(i = strlen(str) - 1; i >= 0; i--){ if(strchr(" \r\n\t", str[i])){ str[i] = '\0'; } else { break; } } } /* update the database of Depot */ void updatedepot(const char *dbname, int act, const char *key, const char *val){ int put, dmode; DEPOT *depot; char *kbuf, *vbuf; put = FALSE; dmode = DP_DOVER; switch(act){ case ACTRECPUTOVER: put = TRUE; dmode = DP_DOVER; break; case ACTRECPUTKEEP: put = TRUE; dmode = DP_DKEEP; break; case ACTRECPUTCAT: put = TRUE; dmode = DP_DCAT; break; case ACTRECOUTONE: break; default: return; } if(!key || !val){ htmlprintf("

Parameters are lack to update the database.

\n"); htmlprintf("
\n"); return; } if(!(depot = dpopen(dbname, DP_OWRITER, -1))){ htmlprintf("

The database file could not open as a writer.

\n"); htmlprintf("
\n"); return; } if(put){ kbuf = cbmemdup(key, -1); vbuf = cbmemdup(val, -1); if(keychop) strchop(kbuf); if(valchop) strchop(vbuf); if(dpput(depot, kbuf, -1, vbuf, -1, dmode)){ htmlprintf("

A record was stored.

\n"); } else if(dpecode == DP_EKEEP){ htmlprintf("

An existing record are kept.

\n"); } else { htmlprintf("

The database has a fatal error.

\n"); } free(vbuf); free(kbuf); } else { if(dpout(depot, key, -1)){ htmlprintf("

A record was deleted.

\n"); } else if(dpecode == DP_ENOITEM){ htmlprintf("

There is no such record.

\n"); } else { htmlprintf("

The database has a fatal error.

\n"); } } if(!dpclose(depot)) htmlprintf("

The database has a fatal error.

\n"); htmlprintf("
\n"); } /* update the database of Curia */ void updatecuria(const char *dbname, int act, const char *key, const char *val){ int put, dmode; CURIA *curia; char *kbuf, *vbuf; put = FALSE; dmode = CR_DOVER; switch(act){ case ACTRECPUTOVER: put = TRUE; dmode = CR_DOVER; break; case ACTRECPUTKEEP: put = TRUE; dmode = CR_DKEEP; break; case ACTRECPUTCAT: put = TRUE; dmode = CR_DCAT; break; case ACTRECOUTONE: break; default: return; } if(!key || !val){ htmlprintf("

Parameters are lack to update the database.

\n"); htmlprintf("
\n"); return; } if(!(curia = cropen(dbname, CR_OWRITER, -1, -1))){ htmlprintf("

The database file could not open as a writer.

\n"); htmlprintf("
\n"); return; } if(put){ kbuf = cbmemdup(key, -1); vbuf = cbmemdup(val, -1); if(keychop) strchop(kbuf); if(valchop) strchop(vbuf); if(crput(curia, kbuf, -1, vbuf, -1, dmode)){ htmlprintf("

A record was stored.

\n"); } else if(dpecode == DP_EKEEP){ htmlprintf("

An existing record are kept.

\n"); } else { htmlprintf("

The database has a fatal error.

\n"); } free(vbuf); free(kbuf); } else { if(crout(curia, key, -1)){ htmlprintf("

A record was deleted.

\n"); } else if(dpecode == DP_ENOITEM){ htmlprintf("

There is no such record.

\n"); } else { htmlprintf("

The database has a fatal error.

\n"); } } if(!crclose(curia)) htmlprintf("

The database has a fatal error.

\n"); htmlprintf("
\n"); } /* update the database of Villa */ void updatevilla(const char *dbname, int act, const char *key, const char *val){ int put, dmode, olist; VILLA *villa; char *kbuf, *vbuf; put = FALSE; dmode = VL_DOVER; olist = FALSE; switch(act){ case ACTRECPUTOVER: put = TRUE; dmode = VL_DOVER; break; case ACTRECPUTKEEP: put = TRUE; dmode = VL_DKEEP; break; case ACTRECPUTDUP: put = TRUE; dmode = VL_DDUP; break; case ACTRECOUTONE: olist = FALSE; break; case ACTRECOUTLIST: olist = TRUE; break; default: return; } if(!key || !val){ htmlprintf("

Parameters are lack to update the database.

\n"); htmlprintf("
\n"); return; } if(!(villa = vlopen(dbname, VL_OWRITER, VL_CMPLEX))){ htmlprintf("

The database file could not open as a writer.

\n"); htmlprintf("
\n"); return; } if(put){ kbuf = cbmemdup(key, -1); vbuf = cbmemdup(val, -1); if(keychop) strchop(kbuf); if(valchop) strchop(vbuf); if(vlput(villa, kbuf, -1, vbuf, -1, dmode)){ htmlprintf("

A record was stored.

\n"); } else if(dpecode == DP_EKEEP){ htmlprintf("

An existing record are kept.

\n"); } else { htmlprintf("

The database has a fatal error.

\n"); } free(vbuf); free(kbuf); } else { if(olist ? vloutlist(villa, key, -1) : vlout(villa, key, -1)){ if(olist){ htmlprintf("

Some records were deleted.

\n"); } else { htmlprintf("

A record was deleted.

\n"); } } else if(dpecode == DP_ENOITEM){ htmlprintf("

There is no such record.

\n"); } else { htmlprintf("

The database has a fatal error.

\n"); } } if(!vlclose(villa)) htmlprintf("

The database has a fatal error.

\n"); htmlprintf("
\n"); } /* list records of Depot */ void depotreclist(const char *dbname){ DEPOT *depot; char *kbuf, *vbuf; int i, ksiz, vsiz; if(!(depot = dpopen(dbname, DP_OREADER, -1))){ htmlprintf("

The database file could not open as a reader.

\n"); return; } dpiterinit(depot); htmlprintf("\n"); htmlprintf("\n"); htmlprintf("\n"); htmlprintf("\n"); htmlprintf("\n"); htmlprintf("\n"); for(i = 1; (kbuf = dpiternext(depot, &ksiz)) != NULL; i++){ if(!(vbuf = dpget(depot, kbuf, ksiz, 0, -1, &vsiz))){ free(kbuf); continue; } htmlprintf("\n"); htmlprintf("\n", i); htmlprintf("\n", kbuf); htmlprintf("\n", vbuf); htmlprintf("\n"); free(vbuf); free(kbuf); } htmlprintf("
#KeysValues
%d%@%@
\n"); dpclose(depot); } /* list records of Curia */ void curiareclist(const char *dbname){ CURIA *curia; char *kbuf, *vbuf; int i, ksiz, vsiz; if(!(curia = cropen(dbname, CR_OREADER, -1, -1))){ htmlprintf("

The database file could not open as a reader.

\n"); return; } criterinit(curia); htmlprintf("\n"); htmlprintf("\n"); htmlprintf("\n"); htmlprintf("\n"); htmlprintf("\n"); htmlprintf("\n"); for(i = 1; (kbuf = criternext(curia, &ksiz)) != NULL; i++){ if(!(vbuf = crget(curia, kbuf, ksiz, 0, -1, &vsiz))){ free(kbuf); continue; } htmlprintf("\n"); htmlprintf("\n", i); htmlprintf("\n", kbuf); htmlprintf("\n", vbuf); htmlprintf("\n"); free(vbuf); free(kbuf); } htmlprintf("
#KeysValues
%d%@%@
\n"); crclose(curia); } /* list records of Villa */ void villareclist(const char *dbname){ VILLA *villa; char *kbuf, *vbuf; int i, ksiz, vsiz; if(!(villa = vlopen(dbname, VL_OREADER, VL_CMPLEX))){ htmlprintf("

The database file could not open as a reader.

\n"); return; } vlcurfirst(villa); htmlprintf("\n"); htmlprintf("\n"); htmlprintf("\n"); htmlprintf("\n"); htmlprintf("\n"); htmlprintf("\n"); for(i = 1; (kbuf = vlcurkey(villa, &ksiz)) != NULL; i++){ if(!(vbuf = vlcurval(villa, &vsiz))){ free(kbuf); vlcurnext(villa); continue; } htmlprintf("\n"); htmlprintf("\n", i); htmlprintf("\n", kbuf); htmlprintf("\n", vbuf); htmlprintf("\n"); free(vbuf); free(kbuf); vlcurnext(villa); } htmlprintf("
#KeysValues
%d%@%@
\n"); vlclose(villa); } /* END OF FILE */ qdbm-1.8.78/cgi/configure.in0000644000175000017500000000506610365614223014630 0ustar mikiomikio# Source of configuration for CGI scripts of QDBM #================================================================ # Generic Settings #================================================================ # Targets AC_INIT(qdbm-cgi, 0.0.1) # Export variables TARGETS="all" # Building paths pathtmp="$PATH" PATH="$HOME/bin:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin" PATH="$PATH:/usr/ccs/bin:/usr/ucb:/usr/xpg4/bin:/usr/xpg6/bin:$pathtmp" LIBRARY_PATH="$HOME/lib:/usr/local/lib:$LIBRARY_PATH" LD_LIBRARY_PATH="$HOME/lib:/usr/local/lib:$LD_LIBRARY_PATH" CPATH="$HOME/include:/usr/local/include:$CPATH" export PATH LIBRARY_PATH LD_LIBRARY_PATH CPATH #================================================================ # Options #================================================================ # Debug mode AC_ARG_ENABLE(debug, [ --enable-debug build for debugging]) if test "$enable_debug" = "yes" then TARGETS="debug" fi # Developping mode AC_ARG_ENABLE(devel, [ --enable-devel build for development]) if test "$enable_devel" = "yes" then TARGETS="devel" fi #================================================================ # Checking Commands to Build with #================================================================ # C compiler AC_PROG_CC if test "$GCC" != "yes" then printf '#================================================================\n' 1>&2 printf '# WARNING: GCC is required to build this package.\n' 1>&2 printf '#================================================================\n' 1>&2 fi #================================================================ # Checking Libraries #================================================================ # Underlying libraries AC_CHECK_LIB(c, main) AC_CHECK_LIB(pthread, main) AC_CHECK_LIB(z, main) AC_CHECK_LIB(lzo2, main) AC_CHECK_LIB(bz2, main) AC_CHECK_LIB(iconv, main) # Fundamental QDBM libraries AC_CHECK_LIB(qdbm, main, true, printf 'checking whether /usr/local/lib/libqdbm.* is... ' if ls /usr/local/lib/libqdbm.* > /dev/null 2>&1 then printf 'yes\n' else printf 'no\n' printf '#================================================================\n' 1>&2 printf '# WARNING: Install QDBM libraries before installation.\n' 1>&2 printf '#================================================================\n' 1>&2 fi ) #================================================================ # Generic Settings #================================================================ # Export variables AC_SUBST(TARGETS) # Targets AC_OUTPUT(Makefile) # END OF FILE qdbm-1.8.78/cgi/cgispex-ja.html0000644000175000017500000004050311426311675015236 0ustar mikiomikio Specifications of CGI Scripts of QDBM (Japanese)

QDBM付属CGIスクリプト仕様書

Copyright (C) 2000-2006 Mikio Hirabayashi
Last Update: Thu, 26 Oct 2006 15:00:20 +0900

目次

  1. 概è¦
  2. ビルド
  3. データベース管ç†ç”¨CGIスクリプト
  4. ファイルアップロード用CGIスクリプト
  5. 全文検索用CGIスクリプト
  6. Webサーãƒã®è¨­å®š

概è¦

ユーティリティもã—ãã¯ã‚¢ãƒ—リケーションã®ã‚µãƒ³ãƒ—ルã¨ã—ã¦ã€QDBMã®ãƒ‘ッケージã«ã¯ä¸‰ã¤ã®CGIスクリプトãŒä»˜å±žã™ã‚‹ã€‚第一ã¯Depotã¨Curiaã¨Villaã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルを管ç†ã™ã‚‹ã‚‚ã®ã§ã‚る。第二ã¯Cabinã®ãƒ¦ãƒ¼ãƒ†ã‚£ãƒªãƒ†ã‚£ã‚’用ã„ã¦ãƒ•ァイルã®ã‚¢ãƒƒãƒ—ロードを行ã†ã‚‚ã®ã§ã‚る。第三ã¯Odeumã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’用ã„ã¦å…¨æ–‡æ¤œç´¢ã‚’行ã†ã‚‚ã®ã§ã‚る。


ビルド

Webサーãƒä¸Šã§CGIãŒåˆ©ç”¨ã§ãã€QDBM㌠`/usr/local' 以下ã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•れã¦ã„ã‚‹ã“ã¨ãŒå¿…è¦ã§ã‚る。

インストール作業ã¯ã€ã‚µãƒ–ディレクトリ `cgi' をカレントディレクトリã«ã—ã¦è¡Œã†ã€‚

cd cgi

ビルド環境を設定ã™ã‚‹ã€‚

./configure

プログラムをビルドã™ã‚‹ã€‚

make

プログラムをインストールã™ã‚‹ã€‚作業㯠`root' ユーザã§è¡Œã†ã€‚

make install

一連ã®ä½œæ¥­ãŒçµ‚ã‚‹ã¨ã€ä»¥ä¸‹ã®ãƒ•ァイルãŒã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•れる。ãã®ä»–ã«ã‚‚文書㌠`/usr/local/share/qdbm/cgi' ã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•れる。

/usr/local/libexec/qadm.cgi
/usr/local/libexec/qupl.cgi
/usr/local/libexec/qfts.cgi
/usr/local/share/qdbm/cgi/qadm.conf
/usr/local/share/qdbm/cgi/qupl.conf
/usr/local/share/qdbm/cgi/qfts.conf

以下ã®å„ã‚»ã‚¯ã‚·ãƒ§ãƒ³ã®æŒ‡ç¤ºã«å¾“ã£ã¦ã€åˆ©ç”¨ã™ã‚‹CGIスクリプトã¨ãã®è¨­å®šãƒ•ァイルをWWWã«å…¬é–‹ã•れãŸãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã«ã‚³ãƒ”ーã™ã‚‹ã€‚


データベース管ç†ç”¨CGIスクリプト

`qadm.cgi' ã¯ã€Depotã¨Curiaã¨Villaã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’管ç†ã™ã‚‹ãŸã‚ã®CGIスクリプトã§ã‚る。ã“れを使ã†ã¨ã€WWWを介ã—ã¦ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®ç®¡ç†ã‚’行ã†ã“ã¨ãŒã§ãる。レコードã®ã‚­ãƒ¼ã¨å€¤ã¯æ–‡å­—列ã§ã‚ã‚‹ã‚‚ã®ã¨ã™ã‚‹ã€‚Villaã®æ¯”較関数ã¯è¾žæ›¸é †ã§ã‚る。利用ã§ãã‚‹æ“作ã¯ã€ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®ä¸€è¦§ã€ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®ä½œæˆã€ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®å‰Šé™¤ã€ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰ã€ãƒ¬ã‚³ãƒ¼ãƒ‰ã®ä¸€è¦§ã€ãƒ¬ã‚³ãƒ¼ãƒ‰ã®è¿½åŠ ã€ãŠã‚ˆã³ãƒ¬ã‚³ãƒ¼ãƒ‰ã®å‰Šé™¤ã§ã‚る。

`qadm.cgi' ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã¯æ¬¡ã®æ‰‹é †ã«å¾“ã†ã€‚CGIãŒåˆ©ç”¨ã§ãるディレクトリ㫠`qdbm.cgi' 㨠`qadm.conf' をコピーã™ã‚‹ã€‚ã¾ãŸã€åŒã˜ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã®ç›´ä¸‹ã« `qadmdir' ã¨ã„ã†åå‰ã®ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã‚’作æˆã™ã‚‹ã€‚例ãˆã°ã€CGIã‚’ç½®ãディレクトリ㌠/home/mikio/public_html ã®å ´åˆã€ä»¥ä¸‹ã®ã‚ˆã†ã«ã™ã‚‹ã€‚

cd /home/mikio/public_html
cp /usr/local/libexec/qadm.cgi .
cp /usr/local/share/qdbm/cgi/qadm.conf .
mkdir qadmdir

`qadmdir' ディレクトリ㯠`qadm.cgi' ã®ãƒ—ロセスãŒèª­ã¿æ›¸ããŠã‚ˆã³å®Ÿè¡Œã§ãるパーミッションã§ã‚ã‚‹å¿…è¦ãŒã‚る。最も簡å˜ã«ã¯ã€ä»¥ä¸‹ã®ã‚ˆã†ã«ã™ã‚‹ã€‚ä»–ã«ã‚‚ã€CGIスクリプトã«setuidビットを立ã¦ãŸã‚Šã€ã„ã‚ゆるsuExecã®ã‚ˆã†ãªæ©Ÿèƒ½ã‚’用ã„る方法もã‚る。

cd /home/mikio/public_html
chmod 1777 qadmdir

`qadm.conf' ã¯è¨­å®šãƒ•ァイルã§ã‚る。デフォルトã§ã¯ä»¥ä¸‹ã®ã‚ˆã†ãªå†…容をæŒã¤ãŒã€ãƒ¦ãƒ¼ã‚¶ãŒä»»æ„ã«ä¿®æ­£ã™ã‚‹ã“ã¨ãŒã§ãる。

encoding: UTF-8
lang: en
title: Administration CGI
datadir: qadmdir
keychop: true
valchop: false

`encoding' ã¯CGIスクリプトã«ã‚ˆã£ã¦è¡¨ç¤ºã•れるページãŠã‚ˆã³ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイル内ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã®æ–‡å­—コードを指定ã™ã‚‹ã€‚`lang' ã¯è¡¨ç¤ºã•れるページã®è¨€èªžã‚’指定ã™ã‚‹ã€‚`title' ã¯è¡¨ç¤ºã•れるページã®ã‚¿ã‚¤ãƒˆãƒ«ã‚’指定ã™ã‚‹ã€‚`datadir' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ã‚¡ã‚¤ãƒ«ãŒæ ¼ç´ã•れるディレクトリã®ãƒ‘スを指定ã™ã‚‹ã€‚`keychop' 㨠`valchop' ã¯ã€ãƒ¬ã‚³ãƒ¼ãƒ‰ã®ã‚­ãƒ¼ã¨å€¤ã®å†…容を正è¦åŒ–ã™ã‚‹ã‹å¦ã‹ã‚’指定ã™ã‚‹ã€‚`true' ã®å ´åˆã¯ã€æœ«å°¾ã®ç©ºç™½ã‚’å–り除ãã€ã‹ã¤æ”¹è¡Œã‚³ãƒ¼ãƒ‰ãŒå†…容ã«å«ã¾ã‚Œãªã„よã†ã«ã™ã‚‹ã€‚

設置ã•れ㟠`qadm.cgi' ã®URLã«Webブラウザを用ã„ã¦ã‚¢ã‚¯ã‚»ã‚¹ã™ã‚‹ã€‚ã‚ã¨ã¯ã€è¡¨ç¤ºã•ã‚ŒãŸæ¡ˆå†…ã«ã—ãŸãŒã£ã¦ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®ç®¡ç†ã‚’行ãˆã°ã‚ˆã„。

自動化ã•れãŸã‚¨ãƒ¼ã‚¸ã‚§ãƒ³ãƒˆãŒãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«ç™»éŒ²ã•れãŸãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’検索ã™ã‚‹ãŸã‚ã«ã€URLã§ç›´æŽ¥ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’指定ã—ã€ãã®å€¤ã®å†…容ãã®ã‚‚ã®ã‚’プレーンテキストã¨ã—ã¦å–å¾—ã™ã‚‹æ©Ÿæ§‹ã‚‚ã‚る。例ãˆã°CGIスクリプトã®URL㌠`http://a.b.c/qadm.cgi' ã§ã‚りã€`staff' ã¨ã„ã†åå‰ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«æ ¼ç´ã•れ㟠`mikio' ã¨ã„ã†ã‚­ãƒ¼ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã®å€¤ã‚’å–り出ã™ã«ã¯ã€ã‚¨ãƒ¼ã‚¸ã‚§ãƒ³ãƒˆã¯ `http://a.b.c/qadm.cgi/staff/mikio' ã‚’å‚ç…§ã™ã‚Œã°ã‚ˆã„。ã™ãªã‚ã¡ã€CGIスクリプトã®URLã®å¾Œã‚ã«ã€`/' ã§åŒºåˆ‡ã£ã¦ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹å(接尾辞ã¯ä¸è¦ï¼‰ã¨ã‚­ãƒ¼ã‚’指定ã™ã‚Œã°ã‚ˆã„。

既存ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルを管ç†å¯¾è±¡ã«ã—ãŸã„å ´åˆã¯ã€`qadmdir' ディレクトリã®ä¸­ã«ãれを置ã‘ã°ã‚ˆã„。ãŸã ã—ã€Depotã«ã‚ˆã‚‹ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルã®åå‰ã«ã¯æŽ¥å°¾è¾žã¨ã—㦠`.dp' ã‚’ã¤ã‘ã€Curiaã«ã‚ˆã‚‹ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã®åå‰ã«ã¯æŽ¥å°¾è¾žã¨ã—㦠`.cr' ã‚’ã¤ã‘ã€Villaã«ã‚ˆã‚‹ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルã®åå‰ã«ã¯æŽ¥å°¾è¾žã¨ã—㦠`.vl' ã‚’ã¤ã‘ã‚‹å¿…è¦ãŒã‚る。例ãˆã° `foo.dp'ã€`bar.cr'ã€`baz.vl' ãªã©ã¨ã™ã‚‹ã€‚ã¾ãŸã€å„データベースファイルã¾ãŸã¯ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã¯CGIスクリプトã®ãƒ—ロセスã«ã‚ˆã£ã¦èª­ã¿æ›¸ãå¯èƒ½ã§ã‚ã‚‹å¿…è¦ãŒã‚る。


ファイルアップロード用CGIスクリプト

`qupl.cgi' ã¯ã€Cabinを使ã£ã¦ãƒ•ァイルをアップロードã™ã‚‹ãŸã‚ã®CGIスクリプトã§ã‚る。ã“れを使ã†ã¨ã€Webサーãƒã«ä»»æ„ã®ãƒ•ァイルをアップロードã™ã‚‹ã“ã¨ãŒã§ãる。ファイルã®ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰ã‚„削除もå¯èƒ½ã§ã‚る。

`qupl.cgi' ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã¯æ¬¡ã®æ‰‹é †ã«å¾“ã†ã€‚CGIãŒåˆ©ç”¨ã§ãるディレクトリ㫠`qupl.cgi' 㨠`qupl.conf' をコピーã™ã‚‹ã€‚ã¾ãŸã€åŒã˜ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã®ç›´ä¸‹ã« `qupldir' ã¨ã„ã†åå‰ã®ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã‚’作æˆã™ã‚‹ã€‚例ãˆã°ã€CGIã‚’ç½®ãディレクトリ㌠/home/mikio/public_html ã®å ´åˆã€ä»¥ä¸‹ã®ã‚ˆã†ã«ã™ã‚‹ã€‚

cd /home/mikio/public_html
cp /usr/local/libexec/qupl.cgi .
cp /usr/local/share/qdbm/cgi/qupl.conf .
mkdir qupldir

`qupldir' ディレクトリ㯠`qupl.cgi' ã®ãƒ—ロセスãŒèª­ã¿æ›¸ããŠã‚ˆã³å®Ÿè¡Œã§ãるパーミッションã§ã‚ã‚‹å¿…è¦ãŒã‚る。最も簡å˜ã«ã¯ã€ä»¥ä¸‹ã®ã‚ˆã†ã«ã™ã‚‹ã€‚ä»–ã«ã‚‚ã€CGIスクリプトã«setuidビットを立ã¦ãŸã‚Šã€ã„ã‚ゆるsuExecã®ã‚ˆã†ãªæ©Ÿèƒ½ã‚’用ã„る方法もã‚る。

cd /home/mikio/public_html
chmod 1777 qupldir

`qupl.conf' ã¯è¨­å®šãƒ•ァイルã§ã‚る。デフォルトã§ã¯ä»¥ä¸‹ã®ã‚ˆã†ãªå†…容をæŒã¤ãŒã€ãƒ¦ãƒ¼ã‚¶ãŒä»»æ„ã«ä¿®æ­£ã™ã‚‹ã“ã¨ãŒã§ãる。

encoding: UTF-8
lang: en
title: Administration CGI
datadir: qupldir
quota: 67108864

`encoding' ã¯CGIスクリプトã«ã‚ˆã£ã¦è¡¨ç¤ºã•れるページãŠã‚ˆã³ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイル内ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã®æ–‡å­—コードを指定ã™ã‚‹ã€‚`lang' ã¯è¡¨ç¤ºã•れるページã®è¨€èªžã‚’指定ã™ã‚‹ã€‚`title' ã¯è¡¨ç¤ºã•れるページã®ã‚¿ã‚¤ãƒˆãƒ«ã‚’指定ã™ã‚‹ã€‚`datadir' ã¯ã‚¢ãƒƒãƒ—ロードã—ãŸãƒ•ã‚¡ã‚¤ãƒ«ãŒæ ¼ç´ã•れるディレクトリã®ãƒ‘スを指定ã™ã‚‹ã€‚`quota' ã¯ã‚¢ãƒƒãƒ—ロードã§ãるファイルã®ç·å®¹é‡ã®ä¸Šé™ã‚’指定ã™ã‚‹ã€‚

設置ã•れ㟠`qupl.cgi' ã®URLã«Webブラウザを用ã„ã¦ã‚¢ã‚¯ã‚»ã‚¹ã™ã‚‹ã€‚ã‚ã¨ã¯ã€è¡¨ç¤ºã•ã‚ŒãŸæ¡ˆå†…ã«ã—ãŸãŒã£ã¦ãƒ•ァイルã®ç®¡ç†ã‚’行ãˆã°ã‚ˆã„。


全文検索用CGIスクリプト

`qfts.cgi' ã¯ã€Odeumã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’用ã„ã¦å…¨æ–‡æ¤œç´¢ã‚’行ã†CGIスクリプトã§ã‚る。ã“れを使ã†ã¨ã€Webサイトã®å…¨æ–‡æ¤œç´¢ã‚’行ã†ã“ã¨ãŒã§ãる。インデックスã®ä½œæˆã¯ã‚³ãƒžãƒ³ãƒ‰ `odidx' を用ã„ã¦è¡Œã„ã€`qfts.cgi' ã«ã‚ˆã£ã¦ãã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®æ¤œç´¢ã‚’行ã†ã€‚検索方å¼ã«ã¯ã€æŒ‡å®šã—ãŸèªžã‚’å…¨ã¦å«ã‚€æ–‡æ›¸ã‚’検索ã™ã‚‹ã€ŒAND検索ã€ã¨ã€æŒ‡å®šã—ãŸèªžã®å°‘ãªãã¨ã‚‚一ã¤ã‚’å«ã‚€ã€ŒOR検索ã€ãŒã‚ã‚‹ã€‚æ¤œç´¢çµæžœã¯ã‚¹ã‚³ã‚¢ã«å¿œã˜ã¦ä¸¦ã¹ã‚‰ã‚Œã‚‹ã€‚

`qfts.cgi' ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã¯æ¬¡ã®æ‰‹é †ã«å¾“ã†ã€‚CGIãŒåˆ©ç”¨ã§ãるディレクトリ㫠`qfts.cgi' 㨠`qfts.conf' をコピーã™ã‚‹ã€‚ã¾ãŸã€åŒã˜ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã®ç›´ä¸‹ã« `casket' ã¨ã„ã†åå‰ã®ã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹ã‚’作æˆã™ã‚‹ã€‚例ãˆã°ã€CGIスクリプトを置ãディレクトリ㌠/home/mikio/public_html ã®å ´åˆã€ä»¥ä¸‹ã®ã‚ˆã†ã«ã™ã‚‹ã€‚

cd /home/mikio/public_html
cp /usr/local/libexec/qfts.cgi .
cp /usr/local/share/qdbm/cgi/qfts.conf .
odidx register casket
odidx relate casket

検索対象ã®ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªãŒCGIスクリプトを置ãディレクトリã®ä¸‹ã«ãªã„å ´åˆã¯ã€ãã“ã«æ¤œç´¢å¯¾è±¡ã®ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã¸ã®ã‚·ãƒ³ãƒœãƒªãƒƒã‚¯ãƒªãƒ³ã‚¯ã‚’作れã°ã‚ˆã„。

ã‚µã‚¤ãƒˆã®æ›´æ–°ãŒã‚ã£ãŸéš›ã«ã¯ã€ä»¥ä¸‹ã®æ‰‹é †ã§ã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹ã‚‚æ›´æ–°ã™ã¹ãã§ã‚る。ã“ã®ä½œæ¥­ã¯ `crontab' ãªã©ã‚’用ã„ã¦è‡ªå‹•化ã™ã‚‹ã¨ã‚ˆã„。

cd /home/mikio/public_html
odidx register casket
odidx purge casket
odidx relate casket
odmgr optimize casket

`qfts.conf' ã¯è¨­å®šãƒ•ァイルã§ã‚る。デフォルトã§ã¯ä»¥ä¸‹ã®ã‚ˆã†ãªå†…容をæŒã¤ãŒã€ãƒ¦ãƒ¼ã‚¶ãŒä»»æ„ã«ä¿®æ­£ã™ã‚‹ã“ã¨ãŒã§ãる。

encoding: ISO-8859-1
lang: en
title: Full-text Search CGI
index: casket
prefix: ./
diridx: index.html
decuri: false
help: <h1>Full-text Search CGI</h1>
help: <p>Input search words into the above form and push the [Search] button.</p>
help: <p>This is a sample application of the inverted API of QDBM.</p>

`encoding' ã¯CGIスクリプトã«ã‚ˆã£ã¦è¡¨ç¤ºã•れるページãŠã‚ˆã³ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイル内ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã®æ–‡å­—コードを指定ã™ã‚‹ã€‚`lang' ã¯è¡¨ç¤ºã•れるページã®è¨€èªžã‚’指定ã™ã‚‹ã€‚`title' ã¯è¡¨ç¤ºã•れるページã®ã‚¿ã‚¤ãƒˆãƒ«ã‚’指定ã™ã‚‹ã€‚`index' ã¯ã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹ã®ãƒ‘スを指定ã™ã‚‹ã€‚`prefix' ã¯å„文書ã®URIã«ã¤ã‘る接頭辞を指定ã™ã‚‹ã€‚例ãˆã° `prefix' ã« `http://x.y.z/foo/' を指定ã™ã‚‹ã¨ã€`./bar/baz.html' ã‚„ `bar/baz.html' 㯠`http://x.y.z/foo/bar/baz.html' ã¨ã—ã¦è¡¨ç¤ºã•れる。`diridx' ã¯ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã®ä»£è¡¨ãƒ•ァイルã®åå‰ã‚’指定ã™ã‚‹ã€‚例ãˆã° `diridx' ã« `index.html' を指定ã™ã‚‹ã¨ã€`./foo/index.html' 㯠`./foo/' ã¨ã—ã¦è¡¨ç¤ºã•れる。`decuri' ã¯ã€å€¤ãŒ `true' ãªã‚‰ã€æ–‡æ›¸ã®URIをデコードã—ã¦è¡¨ç¾ã™ã‚‹ã“ã¨ã‚’指示ã™ã‚‹ã€‚`help' ã¯æœ€åˆã®ãƒšãƒ¼ã‚¸ã§è¡¨ç¤ºã•れるヘルプメッセージを指定ã™ã‚‹ã€‚

設置ã•れ㟠`qfts.cgi' ã®URLã«Webブラウザを用ã„ã¦ã‚¢ã‚¯ã‚»ã‚¹ã™ã‚‹ã€‚ã‚ã¨ã¯ã€è¡¨ç¤ºã•ã‚ŒãŸæ¡ˆå†…ã«ã—ãŸãŒã£ã¦å…¨æ–‡æ¤œç´¢ã‚’行ãˆã°ã‚ˆã„。

インデックスを生æˆã™ã‚‹ã‚³ãƒžãƒ³ãƒ‰ `odidx' ã®è©³ç´°ã«ã¤ã„ã¦ã¯QDBMã®åŸºæœ¬ä»•様書をå‚ç…§ã™ã‚‹ã“ã¨ã€‚å¤§è¦æ¨¡ãªã‚µã‚¤ãƒˆã®ã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹ã‚’生æˆã™ã‚‹éš›ã«ã¯ã€ã‚µã‚¤ã‚ºã‚’å°ã•ãã™ã‚‹ãŸã‚ã«ã€ZLIBを有効ã«ã—ã¦QDBMをビルドã™ã‚‹ã“ã¨ã‚’検討ã™ã¹ãã§ã‚る。


Webサーãƒã®è¨­å®š

CGIスクリプトを利用ã™ã‚‹ã«ã¯ã€WWWサーãƒã®è¨­å®šã§CGIã®å®Ÿè¡Œã‚’許å¯ã™ã‚‹å¿…è¦ãŒã‚る。通常ã®ã‚³ãƒ³ãƒ†ãƒ³ãƒ„ã¨åŒã˜å ´æ‰€ã«CGIスクリプトを設置ã™ã‚‹å ´åˆã€Apacheã®è¨­å®šãƒ•ァイルã«ã¯ä»¥ä¸‹ã®ã‚ˆã†ã«è¨˜è¿°ã™ã‚‹ã€‚

Options ExecCGI
AddHandler cgi-script .cgi

ã‚ã‚‹ã„ã¯CGIスクリプト専用ã®ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã‚’設ã‘ã‚‹å ´åˆã€Apacheã®è¨­å®šãƒ•ァイルã«ã¯ä»¥ä¸‹ã®ã‚ˆã†ã«è¨˜è¿°ã™ã‚‹ã€‚

ScriptAlias /~mikio/cgi-bin/ "/home/mikio/public_html/cgi-bin"

WWWサーãƒã®ãƒ©ã‚¤ãƒ–ラリ検索パス㫠`/usr/local/lib' ãŒå«ã¾ã‚Œã¦ã„ãªã„å ´åˆã€ãã‚Œã‚’æ˜Žç¤ºçš„ã«æŒ‡å®šã™ã‚‹å¿…è¦ãŒã‚ã‚‹ã‹ã‚‚ã—れãªã„。Apacheã®è¨­å®šãƒ•ァイルã«ã¯ä»¥ä¸‹ã®ã‚ˆã†ã«è¨˜è¿°ã™ã‚‹ã€‚

SetEnv LD_LIBRARY_PATH "/lib:/usr/lib:/usr/local/lib"

Microsoftã®IISを利用ã™ã‚‹å ´åˆã€CGIスクリプトã®è¨­ç½®å ´æ‰€ã¨å®Ÿè¡Œæ™‚ã®ã‚«ãƒ¬ãƒ³ãƒˆãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªãŒç•°ãªã‚‹ã€‚後者ã¯ã€Œä»®æƒ³ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã€ã®ãƒ«ãƒ¼ãƒˆã¨ãªã‚‹ã®ã§ã€è¨­å®šãƒ•ァイルã¯ãã“ã«è¨­ç½®ã™ã‚‹å¿…è¦ãŒã‚る。


qdbm-1.8.78/cgi/qfts.c0000644000175000017500000010271710355663556013455 0ustar mikiomikio/************************************************************************************************* * CGI script for full-text search * Copyright (C) 2000-2003 Mikio Hirabayashi * This file is part of QDBM, Quick Database Manager. * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU * Lesser General Public License as published by the Free Software Foundation; either version * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * You should have received a copy of the GNU Lesser General Public License along with QDBM; if * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. *************************************************************************************************/ #include #include #include #include #include #include #include #undef TRUE #define TRUE 1 /* boolean true */ #undef FALSE #define FALSE 0 /* boolean false */ #define CONFFILE "qfts.conf" /* name of the configuration file */ #define DEFENC "US-ASCII" /* default encoding */ #define DEFLANG "en" /* default language */ #define DEFTITLE "Odeum on WWW" /* default title */ #define DEFINDEX "casket" /* directory containing database files */ #define DEFPREFIX "./" /* prefix of the URI of a document */ #define RDATAMAX 262144 /* max size of data to read */ #define NUMBUFSIZ 32 /* size of a buffer for a number */ #define DEFMAX 16 /* default max number of shown documents */ #define SUMTOP 24 /* number of adopted words as top of summary */ #define SUMWIDTH 16 /* number of adopted words around a keyword */ #define SUMWORDMAX 96 /* max number of words in summary */ #define KEYWORDS 16 /* number of shown keywords */ #define EMCLASSNUM 6 /* number of classes for em elements */ #define SCDBNAME "_score" /* name of the database for scores */ #define SCSHOWNUM 8 /* number of shown scores */ #define RELKEYNUM 16 /* number of words to use as relational search */ #define RELDOCMAX 2048 /* number of target words as relational search */ #define RELVECNUM 32 /* number of dimension of score vector */ #define PATHBUFSIZ 1024 /* size of a path buffer */ #define PATHCHR '/' /* delimiter character of path */ enum { UNITAND, UNITOR }; /* for Win32 */ #if defined(_WIN32) #undef PATHCHR #define PATHCHR '\\' #endif /* global variables */ const char *scriptname; /* name of the script */ const char *enc; /* encoding of the page */ const char *lang; /* language of the page */ const char *title; /* title of the page */ /* function prototypes */ int main(int argc, char **argv); const char *skiplabel(const char *str); CBMAP *getparams(void); void senderror(int code, const char *tag, const char *message); void htmlprintf(const char *format, ...); void printmime(void); void printdecl(void); void printhead(void); void showform(const char *phrase, int unit, const char *except, int max); CBLIST *getwords(const char *phrase); void setovec(CBMAP *scores, int *vec); void settvec(CBMAP *osc, CBMAP *tsc, int *vec); void showrelresult(int rel, int max, int skip, const char *index, const char *prefix, const char *diridx, int decuri); void showresult(const CBLIST *words, const char *phrase, int unit, const CBLIST *ewords, const char *except, int max, int skip, const char *index, const char *prefix, const char *diridx, int decuri); void showsummary(const ODDOC *doc, const CBLIST *kwords, const char *phrase, int unit, const char *except, int max, CBMAP *scores); CBMAP *listtomap(const CBLIST *list); void showwords(int id, const CBLIST *words, const char *phrase, int unit, const char *except, int max, const char *index, const char *prefix, const char *diridx, int decuri); void showhelp(const CBLIST *help); /* main routine */ int main(int argc, char **argv){ CBMAP *params; CBLIST *lines, *help, *words, *ewords; const char *tmp, *index, *prefix, *except, *diridx, *phrase; int i, decuri, unit, max, skip, id, rel; /* set configurations */ cbstdiobin(); scriptname = argv[0]; if((tmp = getenv("SCRIPT_NAME")) != NULL) scriptname = tmp; enc = NULL; lang = NULL; title = NULL; index = NULL; prefix = NULL; diridx = NULL; decuri = FALSE; help = cblistopen();; if((lines = cbreadlines(CONFFILE)) != NULL){ for(i = 0; i < cblistnum(lines); i++){ tmp = cblistval(lines, i, NULL); if(cbstrfwmatch(tmp, "encoding:")){ enc = skiplabel(tmp); } else if(cbstrfwmatch(tmp, "lang:")){ lang = skiplabel(tmp); } else if(cbstrfwmatch(tmp, "title:")){ title = skiplabel(tmp); } else if(cbstrfwmatch(tmp, "index:")){ index = skiplabel(tmp); } else if(cbstrfwmatch(tmp, "prefix:")){ prefix = skiplabel(tmp); } else if(cbstrfwmatch(tmp, "diridx:")){ diridx = skiplabel(tmp); } else if(cbstrfwmatch(tmp, "decuri:")){ decuri = !strcmp(skiplabel(tmp), "true"); } else if(cbstrfwmatch(tmp, "help:")){ cblistpush(help, skiplabel(tmp), -1); } } } if(!enc) enc = DEFENC; if(!lang) lang = DEFLANG; if(!title) title = DEFTITLE; if(!index) index = DEFINDEX; if(!prefix) prefix = DEFPREFIX; /* read parameters */ phrase = NULL; except = NULL; unit = UNITAND; max = 0; skip = 0; id = 0; rel = 0; params = getparams(); if((tmp = cbmapget(params, "phrase", -1, NULL)) != NULL) phrase = tmp; if((tmp = cbmapget(params, "except", -1, NULL)) != NULL) except = tmp; if((tmp = cbmapget(params, "unit", -1, NULL)) != NULL) unit = atoi(tmp); if((tmp = cbmapget(params, "max", -1, NULL)) != NULL) max = atoi(tmp); if((tmp = cbmapget(params, "skip", -1, NULL)) != NULL) skip = atoi(tmp); if((tmp = cbmapget(params, "id", -1, NULL)) != NULL) id = atoi(tmp); if((tmp = cbmapget(params, "rel", -1, NULL)) != NULL) rel = atoi(tmp); if(!phrase) phrase = ""; if(!except) except = ""; if(max < 1) max = DEFMAX; if(skip < 0) skip = 0; /* show page */ printmime(); printdecl(); htmlprintf("\n", lang, lang); printhead(); htmlprintf("\n"); showform(phrase, unit, except, max); htmlprintf("
\n"); words = getwords(phrase); ewords = getwords(except); if(id > 0){ showwords(id, words, phrase, unit, except, max, index, prefix, diridx, decuri); } else if(rel > 0){ showrelresult(rel, max, skip, index, prefix, diridx, decuri); } else if(cblistnum(words) > 0){ showresult(words, phrase, unit, ewords, except, max, skip, index, prefix, diridx, decuri); } else if(strlen(phrase) > 0){ htmlprintf("

No effective word was extracted from the phrase.

\n"); } else { showhelp(help); } cblistclose(ewords); cblistclose(words); htmlprintf("
\n"); htmlprintf("\n"); htmlprintf("\n"); /* release resources */ cbmapclose(params); if(lines) cblistclose(lines); cblistclose(help); return 0; } /* skip the label of a line */ const char *skiplabel(const char *str){ if(!(str = strchr(str, ':'))) return str; str++; while(*str != '\0' && (*str == ' ' || *str == '\t')){ str++; } return str; } /* get a map of the CGI parameters */ CBMAP *getparams(void){ CBMAP *params; CBLIST *pairs; char *rbuf, *buf, *key, *val, *dkey, *dval; const char *tmp; int i, len, c; params = cbmapopen(); rbuf = NULL; buf = NULL; if((tmp = getenv("CONTENT_LENGTH")) != NULL && (len = atoi(tmp)) > 0 && len <= RDATAMAX){ rbuf = cbmalloc(len + 1); for(i = 0; i < len && (c = getchar()) != EOF; i++){ rbuf[i] = c; } rbuf[i] = '\0'; if(i == len) buf = rbuf; } else { buf = getenv("QUERY_STRING"); } if(buf != NULL){ buf = cbmemdup(buf, -1); pairs = cbsplit(buf, -1, "&"); for(i = 0; i < cblistnum(pairs); i++){ key = cbmemdup(cblistval(pairs, i, NULL), -1); if((val = strchr(key, '=')) != NULL){ *(val++) = '\0'; dkey = cburldecode(key, NULL); dval = cburldecode(val, NULL); cbmapput(params, dkey, -1, dval, -1, FALSE); free(dval); free(dkey); } free(key); } cblistclose(pairs); free(buf); } free(rbuf); return params; } /* send error status */ void senderror(int code, const char *tag, const char *message){ printf("Status: %d %s\r\n", code, tag); printf("Content-Type: text/plain; charset=US-ASCII\r\n"); printf("\r\n"); printf("%s\n", message); } /* HTML-oriented printf */ void htmlprintf(const char *format, ...){ va_list ap; char *tmp; unsigned char c; va_start(ap, format); while(*format != '\0'){ if(*format == '%'){ format++; switch(*format){ case 's': tmp = va_arg(ap, char *); if(!tmp) tmp = "(null)"; printf("%s", tmp); break; case 'd': printf("%d", va_arg(ap, int)); break; case '@': tmp = va_arg(ap, char *); if(!tmp) tmp = "(null)"; while(*tmp){ switch(*tmp){ case '&': printf("&"); break; case '<': printf("<"); break; case '>': printf(">"); break; case '"': printf("""); break; default: putchar(*tmp); break; } tmp++; } break; case '?': tmp = va_arg(ap, char *); if(!tmp) tmp = "(null)"; while(*tmp){ c = *(unsigned char *)tmp; if((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || (c != '\0' && strchr("_-.", c))){ putchar(c); } else if(c == ' '){ putchar('+'); } else { printf("%%%02X", c); } tmp++; } break; case '%': putchar('%'); break; } } else { putchar(*format); } format++; } va_end(ap); } /* print mime headers */ void printmime(void){ printf("Content-Type: text/html; charset=%s\r\n", enc); printf("Cache-Control: no-cache, must-revalidate\r\n"); printf("Pragma: no-cache\r\n"); printf("\r\n"); fflush(stdout); } /* print the declarations of XHTML */ void printdecl(void){ htmlprintf("\n", enc); htmlprintf("\n"); } /* print headers */ void printhead(void){ htmlprintf("\n"); htmlprintf("\n", enc); htmlprintf("\n"); htmlprintf("\n"); htmlprintf("%@\n", title); htmlprintf("\n"); htmlprintf("\n"); } /* show search form */ void showform(const char *phrase, int unit, const char *except, int max){ int i; htmlprintf("
\n", scriptname); htmlprintf("
\n"); htmlprintf("Phrase: \n", phrase); htmlprintf("\n"); htmlprintf("/\n"); htmlprintf("Except: \n", except); htmlprintf("/\n"); htmlprintf("\n"); htmlprintf("/\n"); htmlprintf("\n"); htmlprintf("
\n"); htmlprintf("
\n"); } /* break phrase into words */ CBLIST *getwords(const char *phrase){ CBLIST *words, *tmp; char *normal; int i; words = cblistopen(); tmp = odbreaktext(phrase); for(i = 0; i < cblistnum(tmp); i++){ normal = odnormalizeword(cblistval(tmp, i, NULL)); if(strlen(normal) > 0) cblistpush(words, normal, -1); free(normal); } cblistclose(tmp); return words; } /* set the original score vector */ void setovec(CBMAP *scores, int *vec){ int i; const char *kbuf; cbmapiterinit(scores); for(i = 0; i < RELVECNUM; i++){ if((kbuf = cbmapiternext(scores, NULL)) != NULL){ vec[i] = atoi(cbmapget(scores, kbuf, -1, NULL)); } else { vec[i] = 0; } } } /* set the target score vector */ void settvec(CBMAP *osc, CBMAP *tsc, int *vec){ int i; const char *kbuf, *vbuf; if(tsc){ cbmapiterinit(osc); for(i = 0; i < RELVECNUM; i++){ if((kbuf = cbmapiternext(osc, NULL)) != NULL){ vbuf = cbmapget(tsc, kbuf, -1, NULL); vec[i] = vbuf ? atoi(vbuf) : 0; } else { vec[i] = 0; } } } else { for(i = 0; i < RELVECNUM; i++){ vec[i] = 0; } } } /* show relational search result */ void showrelresult(int rel, int max, int skip, const char *index, const char *prefix, const char *diridx, int decuri){ ODEUM *odeum; DEPOT *scdb; ODDOC *doc, *tdoc; CBMAP *scores, *tsc; CBLIST *words; ODPAIR *pairs, *last, *tmp; const char *uri, *word, *title, *date, *author; char path[PATHBUFSIZ], *ubuf, *mbuf, *tmbuf, *tubuf, numbuf[NUMBUFSIZ]; int i, j, ulen, msiz, tmsiz, pnum, hnum, lnum, tnum; int ovec[RELVECNUM], tvec[RELVECNUM], id, dnum, wnum; double ival, ustime, sstime, uetime, setime; cbproctime(&ustime, &sstime); if(!(odeum = odopen(index, OD_OREADER))){ htmlprintf("

The index cannot be open because of `%@'.

\n", dperrmsg(dpecode)); return; } sprintf(path, "%s%c%s", index, PATHCHR, SCDBNAME); if(!(scdb = dpopen(path, DP_OREADER, -1))){ htmlprintf("

The score database cannot be open because of `%@'.

\n", dperrmsg(dpecode)); odclose(odeum); return; } if(!(doc = odgetbyid(odeum, rel))){ htmlprintf("

The document cannot be got because of `%@'.

\n", dperrmsg(dpecode)); dpclose(scdb); odclose(odeum); } ubuf = decuri ? cburldecode(oddocuri(doc), NULL) : cbmemdup(oddocuri(doc), -1); if(diridx && cbstrbwmatch(ubuf, diridx)){ ulen = strlen(ubuf) - strlen(diridx); if(ulen > 1 && ubuf[ulen-1] == '/') ubuf[ulen] = '\0'; } uri = ubuf; if(cbstrfwmatch(uri, DEFPREFIX)) uri += strlen(DEFPREFIX); if(!(mbuf = dpget(scdb, (char *)&rel, sizeof(int), 0, -1, &msiz))){ htmlprintf("

Scores cannot be got because of `%@'.

\n", dperrmsg(dpecode)); free(ubuf); oddocclose(doc); dpclose(scdb); odclose(odeum); } scores = cbmapload(mbuf, msiz); words = cbmapkeys(scores); last = NULL; lnum = 0; for(i = 0; i < RELKEYNUM && i < cblistnum(words); i++){ word = cblistval(words, i, NULL); if(!(pairs = odsearch(odeum, word, RELDOCMAX, &pnum))) continue; if((hnum = odsearchdnum(odeum, word)) < 0) hnum = 0; ival = odlogarithm(hnum); ival = (ival * ival) / 4.0; if(ival < 4.0) ival = 4.0; for(j = 0; j < pnum; j++){ pairs[j].score /= ival; } if(last){ tmp = odpairsor(last, lnum, pairs, pnum, &tnum); free(last); free(pairs); last = tmp; lnum = tnum; } else { last = pairs; lnum = pnum; } } if(last && lnum > 0){ setovec(scores, ovec); for(i = 0; i < lnum; i++){ if((tmbuf = dpget(scdb, (char *)&(last[i].id), sizeof(int), 0, -1, &tmsiz)) != NULL){ tsc = cbmapload(tmbuf, tmsiz); free(tmbuf); } else { tsc = NULL; } settvec(scores, tsc, tvec); if(tsc) cbmapclose(tsc); last[i].score = odvectorcosine(ovec, tvec, RELVECNUM) * 10000; if(last[i].score >= 9999) last[i].score = 10000; } odpairssort(last, lnum); for(i = 0; i < lnum; i++){ if(last[i].score < 1){ lnum = i; break; } } } if(last && lnum > 0){ htmlprintf("

Related documents with %@%@ : %d hits

\n", prefix, uri, prefix, uri, lnum); for(i = skip; i < lnum && i < max + skip; i++){ if(!(tdoc = odgetbyid(odeum, last[i].id))){ htmlprintf("
\n"); htmlprintf("
%d: (replaced or purged)
\n", i + 1); htmlprintf("
\n"); continue; } tubuf = decuri ? cburldecode(oddocuri(tdoc), NULL) : cbmemdup(oddocuri(tdoc), -1); if(diridx && cbstrbwmatch(tubuf, diridx)){ ulen = strlen(tubuf) - strlen(diridx); if(ulen > 1 && tubuf[ulen-1] == '/') tubuf[ulen] = '\0'; } uri = tubuf; if(cbstrfwmatch(uri, DEFPREFIX)) uri += strlen(DEFPREFIX); title = oddocgetattr(tdoc, "title"); date = oddocgetattr(tdoc, "date"); author = oddocgetattr(tdoc, "author"); htmlprintf("
\n"); sprintf(numbuf, "%.2f", (double)last[i].score / 100.0); htmlprintf("
%d: %@" " (%@%%)
\n", i + 1, prefix, uri, title && strlen(title) > 0 ? title : "(untitled)", numbuf); tsc = NULL; if(scdb){ id = oddocid(tdoc); if((tmbuf = dpget(scdb, (char *)&id, sizeof(int), 0, -1, &tmsiz)) != NULL){ tsc = cbmapload(tmbuf, tmsiz); free(tmbuf); } } showsummary(tdoc, NULL, "", 0, "", max, tsc); if(tsc) cbmapclose(tsc); htmlprintf("
"); htmlprintf("%@%@", prefix, uri); if(date) htmlprintf(" (%@)", date); if(author) htmlprintf(" (%@)", author); htmlprintf("
\n"); htmlprintf("
\n"); free(tubuf); oddocclose(tdoc); } } else { htmlprintf("

No document hits.

\n"); } if(last) free(last); htmlprintf("
"); if(skip > 0){ htmlprintf("[PREV]", scriptname, rel, max, skip - max); } else { htmlprintf("[PREV]"); } htmlprintf(" "); if(i < lnum){ htmlprintf("[NEXT]", scriptname, rel, max, skip + max); } else { htmlprintf("[NEXT]"); } htmlprintf("
\n"); cbproctime(&uetime, &setime); uetime -= ustime; setime -= sstime; dnum = oddnum(odeum); wnum = odwnum(odeum); cblistclose(words); cbmapclose(scores); free(mbuf); free(ubuf); oddocclose(doc); dpclose(scdb); odclose(odeum); printf("
\n"); printf("The index contains %d documents and %d words.\n", dnum, wnum); printf("Processing time is %.2f sec. (user:%.2f + sys:%.2f)\n", uetime + setime, uetime, setime); printf("
\n"); } /* show search result */ void showresult(const CBLIST *words, const char *phrase, int unit, const CBLIST *ewords, const char *except, int max, int skip, const char *index, const char *prefix, const char *diridx, int decuri){ ODEUM *odeum; DEPOT *scdb; ODPAIR *pairs, *last, *tmp; ODDOC *doc; CBMAP *scores; const char *word, *uri, *title, *date, *author; char path[PATHBUFSIZ], *ubuf, *mbuf; int i, j, smax, pnum, ezpnum, lnum, hnum, tnum, ulen, id, msiz, dnum, wnum; double ival, ustime, sstime, uetime, setime; cbproctime(&ustime, &sstime); if(!(odeum = odopen(index, OD_OREADER))){ htmlprintf("

The index cannot be open because of `%@'.

\n", dperrmsg(dpecode)); return; } sprintf(path, "%s%c%s", index, PATHCHR, SCDBNAME); scdb = dpopen(path, DP_OREADER, -1); htmlprintf("

"); last = NULL; lnum = 0; smax = -1; ezpnum = -1; if(cblistnum(words) < 2 && cblistnum(ewords) < 1) smax = max + skip; for(i = 0; i < cblistnum(words); i++){ word = cblistval(words, i, NULL); if(!(pairs = odsearch(odeum, word, smax, &pnum))) continue; if(smax >= 0) ezpnum = odsearchdnum(odeum, word); if((hnum = odsearchdnum(odeum, word)) < 0) hnum = 0; ival = odlogarithm(hnum); ival = (ival * ival) / 2.0; if(ival < 2.0) ival = 2.0; for(j = 0; j < pnum; j++){ pairs[j].score /= ival; } if(last) htmlprintf(" %@ ", unit == UNITOR ? "+" : "*"); htmlprintf("%@ (%d)", word, hnum); if(last){ if(unit == UNITOR){ tmp = odpairsor(last, lnum, pairs, pnum, &tnum); } else { tmp = odpairsand(last, lnum, pairs, pnum, &tnum); } free(last); free(pairs); last = tmp; lnum = tnum; } else { last = pairs; lnum = pnum; } } for(i = 0; i < cblistnum(ewords); i++){ word = cblistval(ewords, i, NULL); if(!(pairs = odsearch(odeum, word, -1, &pnum))) continue; if((hnum = odsearchdnum(odeum, word)) < 0) hnum = 0; htmlprintf(" - %@ (%d)", word, hnum); if(last){ tmp = odpairsnotand(last, lnum, pairs, pnum, &tnum); free(last); free(pairs); last = tmp; lnum = tnum; } else { free(pairs); } } htmlprintf(" = %d hits

\n", ezpnum >= 0 ? ezpnum : lnum); if(last && lnum > 0){ for(i = skip; i < lnum && i < max + skip; i++){ if(!(doc = odgetbyid(odeum, last[i].id))){ htmlprintf("
\n"); htmlprintf("
%d: (replaced or purged)
\n", i + 1); htmlprintf("
\n"); continue; } ubuf = decuri ? cburldecode(oddocuri(doc), NULL) : cbmemdup(oddocuri(doc), -1); if(diridx && cbstrbwmatch(ubuf, diridx)){ ulen = strlen(ubuf) - strlen(diridx); if(ulen > 1 && ubuf[ulen-1] == '/') ubuf[ulen] = '\0'; } uri = ubuf; if(cbstrfwmatch(uri, DEFPREFIX)) uri += strlen(DEFPREFIX); title = oddocgetattr(doc, "title"); date = oddocgetattr(doc, "date"); author = oddocgetattr(doc, "author"); htmlprintf("
\n"); htmlprintf("
%d: %@ (%d pt.)
\n", i + 1, prefix, uri, title && strlen(title) > 0 ? title : "(untitled)", last[i].score); scores = NULL; if(scdb){ id = oddocid(doc); if((mbuf = dpget(scdb, (char *)&id, sizeof(int), 0, -1, &msiz)) != NULL){ scores = cbmapload(mbuf, msiz); free(mbuf); } } showsummary(doc, words, phrase, unit, except, max, scores); if(scores) cbmapclose(scores); htmlprintf("
"); htmlprintf("%@%@", prefix, uri); if(date) htmlprintf(" (%@)", date); if(author) htmlprintf(" (%@)", author); htmlprintf("
\n"); htmlprintf("
\n"); free(ubuf); oddocclose(doc); } } else { htmlprintf("

No document hits.

\n"); } if(last) free(last); if(ezpnum >= 0) lnum = ezpnum; htmlprintf("
"); if(skip > 0){ htmlprintf("" "[PREV]", scriptname, phrase, unit, except, max, skip - max); } else { htmlprintf("[PREV]"); } htmlprintf(" "); if(i < lnum){ htmlprintf("" "[NEXT]", scriptname, phrase, unit, except, max, skip + max); } else { htmlprintf("[NEXT]"); } htmlprintf("
\n"); cbproctime(&uetime, &setime); uetime -= ustime; setime -= sstime; dnum = oddnum(odeum); wnum = odwnum(odeum); if(scdb) dpclose(scdb); odclose(odeum); printf("
\n"); printf("The index contains %d documents and %d words.\n", dnum, wnum); printf("Processing time is %.2f sec. (user:%.2f + sys:%.2f)\n", uetime + setime, uetime, setime); printf("
\n"); } /* show summary of a document */ void showsummary(const ODDOC *doc, const CBLIST *kwords, const char *phrase, int unit, const char *except, int max, CBMAP *scores){ const CBLIST *nwords, *awords; CBMAP *kmap, *map; const char *normal, *asis, *kbuf; int i, j, num, lnum, tnum, nwsiz, awsiz, pv, bi, first, em; htmlprintf("
"); num = SUMWORDMAX; nwords = oddocnwords(doc); awords = oddocawords(doc); kmap = kwords ? listtomap(kwords) : cbmapopen(); map = kwords ? listtomap(kwords) : cbmapopen(); lnum = cblistnum(nwords); tnum = 0; first = TRUE; em = FALSE; for(i = 0; i < lnum && tnum < (kwords ? SUMTOP : SUMWORDMAX); i++){ normal = cblistval(nwords, i, &nwsiz); asis = cblistval(awords, i, &awsiz); if(awsiz < 1) continue; cbmapout(map, normal, nwsiz); if(normal[0] != '\0' && cbmapget(kmap, normal, nwsiz, NULL)){ if(!first) htmlprintf(" "); if(!em) htmlprintf("", kwords ? cblistlsearch(kwords, normal, nwsiz) % EMCLASSNUM : 0); em = TRUE; } else { if(em) htmlprintf(""); if(!first) htmlprintf(" "); em = FALSE; } htmlprintf("%@", asis); first = FALSE; tnum++; num--; } if(em) htmlprintf(""); htmlprintf(" ..."); em = FALSE; pv = i; while(i < lnum){ if(cbmaprnum(map) < 1){ cbmapclose(map); map = kwords ? listtomap(kwords) : cbmapopen(); } normal = cblistval(nwords, i, &nwsiz); if(cbmapget(map, normal, nwsiz, NULL)){ bi = i - SUMWIDTH / 2; bi = bi > pv ? bi : pv; for(j = bi; j < lnum && j <= bi + SUMWIDTH; j++){ normal = cblistval(nwords, j, &nwsiz); asis = cblistval(awords, j, &awsiz); if(awsiz < 1) continue; cbmapout(map, normal, nwsiz); if(normal[0] != '\0' && cbmapget(kmap, normal, nwsiz, NULL)){ htmlprintf(" "); if(!em) htmlprintf("", kwords ? cblistlsearch(kwords, normal, nwsiz) % EMCLASSNUM : 0); htmlprintf("%@", asis); em = TRUE; } else { if(em) htmlprintf(""); htmlprintf(" "); htmlprintf("%@", asis); em = FALSE; } num--; } if(em) htmlprintf(""); htmlprintf(" ..."); em = FALSE; i = j; pv = i; } else { i++; } if(num <= 0) break; } if(pv < lnum - SUMWIDTH && num > SUMWIDTH){ for(i = pv; i < lnum && num > 0; i++){ asis = cblistval(awords, i, NULL); htmlprintf(" %@", asis); num--; } htmlprintf(" ..."); } htmlprintf(" " "[more]", scriptname, oddocid(doc), phrase, unit, except, max); if(scores){ htmlprintf("
("); cbmapiterinit(scores); for(i = 0; i < SCSHOWNUM && (kbuf = cbmapiternext(scores, NULL)) != NULL; i++){ if(i > 0) htmlprintf(" / "); if(strlen(phrase) > 0){ htmlprintf("%@", scriptname, phrase, kbuf, unit, except, max, kbuf); } else { htmlprintf("%@", scriptname, kbuf, unit, except, max, kbuf); } } htmlprintf(") : [related]
", scriptname, max, oddocid(doc)); } cbmapclose(map); cbmapclose(kmap); htmlprintf("
\n"); } /* get a map made from a list */ CBMAP *listtomap(const CBLIST *list){ CBMAP *map; const char *tmp; int i, tsiz; map = cbmapopen(); for(i = 0; i < cblistnum(list); i++){ tmp = cblistval(list, i, &tsiz); cbmapput(map, tmp, tsiz, "", 0, FALSE); } return map; } /* show words in a document */ void showwords(int id, const CBLIST *words, const char *phrase, int unit, const char *except, int max, const char *index, const char *prefix, const char *diridx, int decuri){ ODEUM *odeum; ODDOC *doc; const CBLIST *awords, *nwords; CBLIST *kwords; CBMAP *kmap; const char *uri, *title, *date, *author, *kword, *asis, *normal; char *ubuf; int i, wnum, nwsiz, awsiz, first, em, ulen; if(!(odeum = odopen(index, OD_OREADER))){ htmlprintf("

The index cannot be open because of `%@'.

\n", dperrmsg(dpecode)); return; } if((doc = odgetbyid(odeum, id)) != NULL){ ubuf = decuri ? cburldecode(oddocuri(doc), NULL) : cbmemdup(oddocuri(doc), -1); if(diridx && cbstrbwmatch(ubuf, diridx)){ ulen = strlen(ubuf) - strlen(diridx); if(ulen > 1 && ubuf[ulen-1] == '/') ubuf[ulen] = '\0'; } uri = ubuf; if(cbstrfwmatch(uri, DEFPREFIX)) uri += strlen(DEFPREFIX); title = oddocgetattr(doc, "title"); date = oddocgetattr(doc, "date"); author = oddocgetattr(doc, "author"); awords = oddocawords(doc); nwords = oddocnwords(doc); htmlprintf("
ID: %d
\n", oddocid(doc)); htmlprintf("
URI: %@%@
\n", prefix, uri, prefix, uri); if(title) htmlprintf("
Title: %@
\n", title); if(date) htmlprintf("
Date: %@
\n", date); if(author) htmlprintf("
Author: %@
\n", author); kmap = oddocscores(doc, KEYWORDS, odeum); kwords = cbmapkeys(kmap); htmlprintf("
Keywords: "); for(i = 0; i < cblistnum(kwords); i++){ kword = cblistval(kwords, i, NULL); if(i > 0) htmlprintf(", "); if(strlen(phrase) > 0){ htmlprintf("%@", scriptname, phrase, kword, unit, except, max, kword); } else { htmlprintf("%@", scriptname, kword, unit, except, max, kword); } } htmlprintf(" : [related]", scriptname, max, id); htmlprintf("
\n"); cblistclose(kwords); cbmapclose(kmap); wnum = cblistnum(awords); kmap = listtomap(words); htmlprintf("
\n"); htmlprintf("
Words: %d (or more)
\n", wnum); htmlprintf("
"); first = TRUE; em = FALSE; for(i = 0; i < wnum; i++){ normal = cblistval(nwords, i, &nwsiz); asis = cblistval(awords, i, &awsiz); if(awsiz < 1) continue; if(normal[0] != '\0' && cbmapget(kmap, normal, nwsiz, NULL)){ if(!first) htmlprintf(" "); if(!em) htmlprintf("", cblistlsearch(words, normal, nwsiz) % EMCLASSNUM); em = TRUE; } else { if(em) htmlprintf(""); if(!first) htmlprintf(" "); em = FALSE; } htmlprintf("%@", asis); first = FALSE; } if(em) htmlprintf(""); htmlprintf(" ..."); htmlprintf("
\n"); htmlprintf("
\n"); cbmapclose(kmap); free(ubuf); oddocclose(doc); } else { htmlprintf("

Retrieving the document failed because of `%@'.

\n", dperrmsg(dpecode)); } odclose(odeum); } /* show help message */ void showhelp(const CBLIST *help){ int i; for(i = 0; i < cblistnum(help); i++){ htmlprintf("%s\n", cblistval(help, i, NULL)); } htmlprintf("
Powered by QDBM %@.
\n", dpversion); } /* END OF FILE */ qdbm-1.8.78/cgi/qupl.c0000644000175000017500000003530610431150420013430 0ustar mikiomikio/************************************************************************************************* * CGI script for file uploader * Copyright (C) 2000-2003 Mikio Hirabayashi * This file is part of QDBM, Quick Database Manager. * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU * Lesser General Public License as published by the Free Software Foundation; either version * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * You should have received a copy of the GNU Lesser General Public License along with QDBM; if * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. *************************************************************************************************/ #include #include #include #include #include #include #include #include #undef TRUE #define TRUE 1 /* boolean true */ #undef FALSE #define FALSE 0 /* boolean false */ #define CONFFILE "qupl.conf" /* name of the configuration file */ #define DEFENC "US-ASCII" /* default encoding */ #define DEFLANG "en" /* default language */ #define DEFTITLE "File Uploader" /* default title */ #define DEFDATADIR "qupldir" /* directory containing files */ /* global variables */ const char *scriptname; /* name of the script */ const char *enc; /* encoding of the page */ const char *lang; /* language of the page */ const char *title; /* title of the page */ int quota; /* limit of the total size */ /* function prototypes */ int main(int argc, char **argv); const char *skiplabel(const char *str); void htmlprintf(const char *format, ...); int getdirsize(const char *path); const char *datestr(time_t t); const char *gettype(const char *path); /* main routine */ int main(int argc, char **argv){ CBLIST *lines, *parts, *files; CBMAP *params; FILE *ifp; const char *tmp, *datadir, *body, *sname; char *wp, *bound, *cdata, *filedata, *filename, *ebuf, *dbuf, *getname, *delname, numbuf[32]; int i, clen, blen, filesize, c, sdir, ssize, total; time_t stime; /* set configurations */ cbstdiobin(); scriptname = argv[0]; if((tmp = getenv("SCRIPT_NAME")) != NULL) scriptname = tmp; enc = NULL; lang = NULL; title = NULL; datadir = NULL; quota = 0; if((lines = cbreadlines(CONFFILE)) != NULL){ for(i = 0; i < cblistnum(lines); i++){ tmp = cblistval(lines, i, NULL); if(cbstrfwmatch(tmp, "encoding:")){ enc = skiplabel(tmp); } else if(cbstrfwmatch(tmp, "lang:")){ lang = skiplabel(tmp); } else if(cbstrfwmatch(tmp, "title:")){ title = skiplabel(tmp); } else if(cbstrfwmatch(tmp, "datadir:")){ datadir = skiplabel(tmp); } else if(cbstrfwmatch(tmp, "quota:")){ quota = atoi(skiplabel(tmp)); } } } if(!enc) enc = DEFENC; if(!lang) lang = DEFLANG; if(!title) title = DEFTITLE; if(!datadir) datadir = DEFDATADIR; if(quota < 0) quota = 0; /* read parameters */ filedata = NULL; filesize = 0; filename = NULL; getname = NULL; delname = NULL; if((tmp = getenv("REQUEST_METHOD")) != NULL && !strcmp(tmp, "POST") && (tmp = getenv("CONTENT_LENGTH")) != NULL && (clen = atoi(tmp)) > 0 && (tmp = getenv("CONTENT_TYPE")) != NULL && cbstrfwmatch(tmp, "multipart/form-data") && (tmp = strstr(tmp, "boundary=")) != NULL){ tmp += 9; if(*tmp == '"') tmp++; bound = cbmemdup(tmp, -1); if((wp = strchr(bound, ';')) != NULL) *wp = '\0'; cdata = cbmalloc(clen + 1); for(i = 0; i < clen && (c = getchar()) != EOF; i++){ cdata[i] = c; } parts = cbmimeparts(cdata, clen, bound); if(cblistnum(parts) > 0){ body = cblistval(parts, 0, &blen); params = cbmapopen(); filedata = cbmimebreak(body, blen, params, &filesize); if((tmp = cbmapget(params, "FILENAME", -1, NULL)) != NULL) filename = cbmemdup(tmp, -1); cbmapclose(params); } cblistclose(parts); free(cdata); free(bound); } else if((tmp = getenv("PATH_INFO")) != NULL){ if(tmp[0] == '/') tmp++; getname = cburldecode(tmp, NULL); if(cbstrfwmatch(getname, "../") || strstr(getname, "/../") != NULL){ free(getname); getname = NULL; } } else if((tmp = getenv("QUERY_STRING")) != NULL && (tmp = strstr(tmp, "delfile="))){ tmp += 8; delname = cburldecode(tmp, NULL); if(cbstrfwmatch(delname, "../") || strstr(delname, "/../") != NULL){ free(delname); delname = NULL; } } if(getname){ /* send data of the file */ if(chdir(datadir) == 0 && (ifp = fopen(getname, "rb")) != NULL){ printf("Content-Type: %s\r\n", gettype(getname)); printf("Cache-Control: no-cache, must-revalidate\r\n"); printf("Pragma: no-cache\r\n"); printf("\r\n"); while((c = fgetc(ifp)) != EOF){ putchar(c); } fclose(ifp); } else { printf("Status: 404 Not Found\r\n"); printf("Content-Type: text/plain; charset=%s\r\n", enc); printf("Cache-Control: no-cache, must-revalidate\r\n"); printf("Pragma: no-cache\r\n"); printf("\r\n"); printf("Not Found\n"); printf("%s\n", getname); } } else { /* output headers */ printf("Content-Type: text/html; charset=%s\r\n", enc); printf("Cache-Control: no-cache, must-revalidate\r\n"); printf("Pragma: no-cache\r\n"); printf("\r\n"); htmlprintf("\n", enc); htmlprintf("\n"); htmlprintf("\n", lang, lang); htmlprintf("\n"); htmlprintf("\n", enc); htmlprintf("\n"); htmlprintf("\n"); htmlprintf("%@\n", title); htmlprintf("\n"); htmlprintf("\n"); htmlprintf("\n"); htmlprintf("

%@

\n", title); htmlprintf("
\n"); htmlprintf("
\n", scriptname); htmlprintf("
\n"); htmlprintf("\n"); htmlprintf("\n"); htmlprintf("[RELOAD]\n", scriptname); htmlprintf("
\n"); htmlprintf("
\n"); htmlprintf("
\n"); /* change the currnt directory */ if(chdir(datadir) == -1){ htmlprintf("

Changing the current directory was failed.

\n"); htmlprintf("
\n"); } else { /* save the file */ if(filedata && filename){ sname = filename; if((ebuf = cbiconv(filename, -1, enc, "UTF-8", NULL, NULL)) != NULL) sname = ebuf; if((tmp = strrchr(sname, '/')) != NULL) sname = tmp + 1; if((tmp = strrchr(sname, '\\')) != NULL) sname = tmp + 1; if(ebuf){ while((tmp = strstr(sname, "\xc2\xa5")) != NULL){ sname = tmp + 2; } } dbuf = NULL; if(ebuf && (dbuf = cbiconv(sname, -1, "UTF-8", enc, NULL, NULL)) != NULL) sname = dbuf; if(getdirsize(".") + filesize > quota){ htmlprintf("

Exceeding the quota. -- %@

\n", sname); } else if(!cbwritefile(sname, filedata, filesize)){ htmlprintf("

Uploading was failed. -- %@

\n", sname); } else { htmlprintf("

Uploading was succeeded. -- %@

\n", sname); } htmlprintf("
\n"); free(dbuf); free(ebuf); } else if(delname){ /* delete the file */ if(unlink(delname) == 0){ htmlprintf("

Deleting was succeeded. -- %@

\n", delname); } else { htmlprintf("

Deleting was failed. -- %@

\n", delname); } htmlprintf("
\n"); } /* show the file list */ if((files = cbdirlist(".")) != NULL){ cblistsort(files); htmlprintf("\n"); htmlprintf("\n"); htmlprintf("\n"); htmlprintf("\n"); htmlprintf("\n"); htmlprintf("\n"); htmlprintf("\n"); for(i = 0; i < cblistnum(files); i++){ sname = cblistval(files, i, NULL); if(!strcmp(sname, ".") || !strcmp(sname, "..")) continue; if(!cbfilestat(sname, &sdir, &ssize, &stime) || sdir) continue; htmlprintf("\n"); htmlprintf("\n", sname); htmlprintf("\n", ssize); htmlprintf("\n", datestr(stime)); htmlprintf("\n"); htmlprintf("\n"); } htmlprintf("
NameSizeModified TimeActions
%@%d%@\n"); htmlprintf("[GET]", scriptname, sname); htmlprintf(" / "); htmlprintf("[DEL]", scriptname, sname); htmlprintf("
\n"); cblistclose(files); total = getdirsize("."); sprintf(numbuf, "%.2f%%", (total * 100.0) / quota); htmlprintf("
Capacity: %@ (%d/%d)
\n", numbuf, total, quota); } else { htmlprintf("

Listing files in the data directory was failed.

\n"); } htmlprintf("
\n"); } /* output footers */ htmlprintf("
Powered by QDBM %@.
\n", dpversion); htmlprintf("\n"); htmlprintf("\n"); } /* release resources */ if(getname) free(getname); if(delname) free(delname); if(filename) free(filename); if(filedata) free(filedata); if(lines) cblistclose(lines); return 0; } /* skip the label of a line */ const char *skiplabel(const char *str){ if(!(str = strchr(str, ':'))) return str; str++; while(*str != '\0' && (*str == ' ' || *str == '\t')){ str++; } return str; } /* HTML-oriented printf */ void htmlprintf(const char *format, ...){ va_list ap; char *tmp; unsigned char c; va_start(ap, format); while(*format != '\0'){ if(*format == '%'){ format++; switch(*format){ case 's': tmp = va_arg(ap, char *); if(!tmp) tmp = "(null)"; printf("%s", tmp); break; case 'd': printf("%d", va_arg(ap, int)); break; case '@': tmp = va_arg(ap, char *); if(!tmp) tmp = "(null)"; while(*tmp){ switch(*tmp){ case '&': printf("&"); break; case '<': printf("<"); break; case '>': printf(">"); break; case '"': printf("""); break; default: putchar(*tmp); break; } tmp++; } break; case '?': tmp = va_arg(ap, char *); if(!tmp) tmp = "(null)"; while(*tmp){ c = *(unsigned char *)tmp; if((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || (c != '\0' && strchr("_-.", c))){ putchar(c); } else if(c == ' '){ putchar('+'); } else { printf("%%%02X", c); } tmp++; } break; case '%': putchar('%'); break; } } else { putchar(*format); } format++; } va_end(ap); } /* get the total size of files in a directory */ int getdirsize(const char *path){ CBLIST *files; const char *sname; int i, total, isdir, size; total = 0; if((files = cbdirlist(path)) != NULL){ for(i = 0; i < cblistnum(files); i++){ sname = cblistval(files, i, NULL); if(!strcmp(sname, ".") || !strcmp(sname, "..")) continue; if(!cbfilestat(sname, &isdir, &size, NULL) || isdir) continue; total += size; } } return total; } /* get static string of the date */ const char *datestr(time_t t){ static char buf[32]; struct tm *stp; if(!(stp = localtime(&t))) return "0000/00/00 00:00:00"; sprintf(buf, "%04d/%02d/%02d %02d:%02d:%02d", stp->tm_year + 1900, stp->tm_mon + 1, stp->tm_mday, stp->tm_hour, stp->tm_min, stp->tm_sec); return buf; } /* get the media type of a file */ const char *gettype(const char *path){ char *types[] = { ".txt", "text/plain", ".asc", "text/plain", ".html", "text/html", ".htm", "text/html", ".mht", "message/rfc822", ".sgml", "application/sgml", ".sgm", "application/sgml", ".xml", "application/xml", ".rtf", "application/rtf", ".pdf", "application/pdf", ".doc", "application/msword", ".xls", "application/vnd.ms-excel", ".ppt", "application/vnd.ms-powerpoint", ".xdw", "application/vnd.fujixerox.docuworks", ".zip", "application/zip", ".tar", "application/x-tar", ".gz", "application/x-gzip", ".png", "image/png", ".gif", "image/gif", ".jpg", "image/jpeg", ".jpeg", "image/jpeg", ".tif", "image/tiff", ".tiff", "image/tiff", ".bmp", "image/bmp", ".mid", "audio/midi", ".midi", "audio/midi", ".mp3", "audio/mpeg", ".wav", "audio/x-wav", ".mpg", "video/mpeg", ".mpeg", "video/mpeg", NULL }; int i; for(i = 0; types[i]; i += 2){ if(cbstrbwimatch(path, types[i])) return types[i+1]; } return "application/octet-stream"; } /* END OF FILE */ qdbm-1.8.78/cgi/qupl.conf0000644000175000017500000000011710110342612014123 0ustar mikiomikioencoding: UTF-8 lang: en title: File Uploader datadir: qupldir quota: 67108864 qdbm-1.8.78/cgi/configure0000755000175000017500000034202611426320067014225 0ustar mikiomikio#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.65 for qdbm-cgi 0.0.1. # # # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, # 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, # Inc. # # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi " as_required="as_fn_return () { (exit \$1); } as_fn_success () { as_fn_return 0; } as_fn_failure () { as_fn_return 1; } as_fn_ret_success () { return 0; } as_fn_ret_failure () { return 1; } exitcode=0 as_fn_success || { exitcode=1; echo as_fn_success failed.; } as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : else exitcode=1; echo positional parameters were not saved. fi test x\$exitcode = x0 || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1" if (eval "$as_required") 2>/dev/null; then : as_have_required=yes else as_have_required=no fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. as_shell=$as_dir/$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : CONFIG_SHELL=$as_shell as_have_required=yes if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : break 2 fi fi done;; esac as_found=false done $as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : CONFIG_SHELL=$SHELL as_have_required=yes fi; } IFS=$as_save_IFS if test "x$CONFIG_SHELL" != x; then : # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV export CONFIG_SHELL exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"} fi if test x$as_have_required = xno; then : $as_echo "$0: This script requires a shell more modern than all" $as_echo "$0: the shells that I found on your system." if test x${ZSH_VERSION+set} = xset ; then $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" $as_echo "$0: be upgraded to zsh 4.3.4 or later." else $as_echo "$0: Please tell bug-autoconf@gnu.org about your system, $0: including any error possibly output before this $0: message. Then install a modern shell, or manually run $0: the script under such a shell if you do have one." fi exit 1 fi fi fi SHELL=${CONFIG_SHELL-/bin/sh} export SHELL # Unset more variables known to interfere with behavior of common tools. CLICOLOR_FORCE= GREP_OPTIONS= unset CLICOLOR_FORCE GREP_OPTIONS ## --------------------- ## ## M4sh Shell Functions. ## ## --------------------- ## # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error "cannot create directory $as_dir" } # as_fn_mkdir_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith # as_fn_error ERROR [LINENO LOG_FD] # --------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with status $?, using 1 if that was 0. as_fn_error () { as_status=$?; test $as_status -eq 0 && as_status=1 if test "$3"; then as_lineno=${as_lineno-"$2"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $1" >&$3 fi $as_echo "$as_me: error: $1" >&2 as_fn_exit $as_status } # as_fn_error if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits as_lineno_1=$LINENO as_lineno_1a=$LINENO as_lineno_2=$LINENO as_lineno_2a=$LINENO eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -p'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -p' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -p' fi else as_ln_s='cp -p' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi if test -x / >/dev/null 2>&1; then as_test_x='test -x' else if ls -dL / >/dev/null 2>&1; then as_ls_L_option=L else as_ls_L_option= fi as_test_x=' eval sh -c '\'' if test -d "$1"; then test -d "$1/."; else case $1 in #( -*)set "./$1";; esac; case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( ???[sx]*):;;*)false;;esac;fi '\'' sh ' fi as_executable_p=$as_test_x # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME='qdbm-cgi' PACKAGE_TARNAME='qdbm-cgi' PACKAGE_VERSION='0.0.1' PACKAGE_STRING='qdbm-cgi 0.0.1' PACKAGE_BUGREPORT='' PACKAGE_URL='' ac_subst_vars='LTLIBOBJS LIBOBJS TARGETS OBJEXT EXEEXT ac_ct_CC CPPFLAGS LDFLAGS CFLAGS CC target_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_URL PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL' ac_subst_files='' ac_user_opts=' enable_option_checking enable_debug enable_devel ' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS' # Initialize some variables set by options. ac_init_help= ac_init_version=false ac_unrecognized_opts= ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) as_fn_error "unrecognized option: \`$ac_option' Try \`$0 --help' for more information." ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) as_fn_error "invalid variable name: \`$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` as_fn_error "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) as_fn_error "unrecognized options: $ac_unrecognized_opts" ;; *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi # Check all directory arguments for consistency. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir do eval ac_val=\$$ac_var # Remove trailing slashes. case $ac_val in */ ) ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` eval $ac_var=\$ac_val;; esac # Be sure to have absolute directory names. case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac as_fn_error "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe $as_echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. If a cross compiler is detected then cross compile mode will be used." >&2 elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || as_fn_error "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || as_fn_error "pwd does not report name of working directory" # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." as_fn_error "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures qdbm-cgi 0.0.1 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/qdbm-cgi] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of qdbm-cgi 0.0.1:";; esac cat <<\_ACEOF Optional Features: --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --enable-debug build for debugging --enable-devel build for development Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to the package provider. _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for guested configure. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF qdbm-cgi configure 0.0.1 generated by GNU Autoconf 2.65 Copyright (C) 2009 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi ## ------------------------ ## ## Autoconf initialization. ## ## ------------------------ ## # ac_fn_c_try_compile LINENO # -------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} as_fn_set_status $ac_retval } # ac_fn_c_try_compile # ac_fn_c_try_link LINENO # ----------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} as_fn_set_status $ac_retval } # ac_fn_c_try_link cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by qdbm-cgi $as_me 0.0.1, which was generated by GNU Autoconf 2.65. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. $as_echo "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) as_fn_append ac_configure_args1 " '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done { ac_configure_args0=; unset ac_configure_args0;} { ac_configure_args1=; unset ac_configure_args1;} # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo cat <<\_ASBOX ## ---------------- ## ## Cache variables. ## ## ---------------- ## _ASBOX echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo cat <<\_ASBOX ## ----------------- ## ## Output variables. ## ## ----------------- ## _ASBOX echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then cat <<\_ASBOX ## ------------------- ## ## File substitutions. ## ## ------------------- ## _ASBOX echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then cat <<\_ASBOX ## ----------- ## ## confdefs.h. ## ## ----------- ## _ASBOX echo cat confdefs.h echo fi test "$ac_signal" != 0 && $as_echo "$as_me: caught signal $ac_signal" $as_echo "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h $as_echo "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_URL "$PACKAGE_URL" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. ac_site_file1=NONE ac_site_file2=NONE if test -n "$CONFIG_SITE"; then ac_site_file1=$CONFIG_SITE elif test "x$prefix" != xNONE; then ac_site_file1=$prefix/share/config.site ac_site_file2=$prefix/etc/config.site else ac_site_file1=$ac_default_prefix/share/config.site ac_site_file2=$ac_default_prefix/etc/config.site fi for ac_site_file in "$ac_site_file1" "$ac_site_file2" do test "x$ac_site_file" = xNONE && continue if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 $as_echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 $as_echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 $as_echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then # differences in whitespace do not lead to failure. ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 $as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 $as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 $as_echo "$as_me: former value: \`$ac_old_val'" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 $as_echo "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 $as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} as_fn_error "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## ## -------------------- ## ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu # Export variables TARGETS="all" # Building paths pathtmp="$PATH" PATH="$HOME/bin:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin" PATH="$PATH:/usr/ccs/bin:/usr/ucb:/usr/xpg4/bin:/usr/xpg6/bin:$pathtmp" LIBRARY_PATH="$HOME/lib:/usr/local/lib:$LIBRARY_PATH" LD_LIBRARY_PATH="$HOME/lib:/usr/local/lib:$LD_LIBRARY_PATH" CPATH="$HOME/include:/usr/local/include:$CPATH" export PATH LIBRARY_PATH LD_LIBRARY_PATH CPATH #================================================================ # Options #================================================================ # Debug mode # Check whether --enable-debug was given. if test "${enable_debug+set}" = set; then : enableval=$enable_debug; fi if test "$enable_debug" = "yes" then TARGETS="debug" fi # Developping mode # Check whether --enable-devel was given. if test "${enable_devel+set}" = set; then : enableval=$enable_devel; fi if test "$enable_devel" = "yes" then TARGETS="devel" fi #================================================================ # Checking Commands to Build with #================================================================ # C compiler ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_CC+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_ac_ct_CC+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_CC+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_CC+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_CC+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_ac_ct_CC+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error "no acceptable C compiler found in \$PATH See \`config.log' for more details." "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 $as_echo_n "checking whether the C compiler works... " >&6; } ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # The possible output files: ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { { ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link_default") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an `-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else ac_file='' fi if test -z "$ac_file"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { as_fn_set_status 77 as_fn_error "C compiler cannot create executables See \`config.log' for more details." "$LINENO" 5; }; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 $as_echo_n "checking for C compiler default output file name... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 $as_echo "$ac_file" >&6; } ac_exeext=$ac_cv_exeext rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 $as_echo_n "checking for suffix of executables... " >&6; } if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error "cannot compute suffix of executables: cannot compile and link See \`config.log' for more details." "$LINENO" 5; } fi rm -f conftest conftest$ac_cv_exeext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 $as_echo "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { FILE *f = fopen ("conftest.out", "w"); return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF ac_clean_files="$ac_clean_files conftest.out" # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 $as_echo_n "checking whether we are cross compiling... " >&6; } if test "$cross_compiling" != yes; then { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if { ac_try='./conftest$ac_cv_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error "cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details." "$LINENO" 5; } fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 $as_echo "$cross_compiling" >&6; } rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 $as_echo_n "checking for suffix of object files... " >&6; } if test "${ac_cv_objext+set}" = set; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error "cannot compute suffix of object files: cannot compile See \`config.log' for more details." "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 $as_echo "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if test "${ac_cv_c_compiler_gnu+set}" = set; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if test "${ac_cv_prog_cc_g+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if test "${ac_cv_prog_cc_c89+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test "$GCC" != "yes" then printf '#================================================================\n' 1>&2 printf '# WARNING: GCC is required to build this package.\n' 1>&2 printf '#================================================================\n' 1>&2 fi #================================================================ # Checking Libraries #================================================================ # Underlying libraries { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lc" >&5 $as_echo_n "checking for main in -lc... " >&6; } if test "${ac_cv_lib_c_main+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lc $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_c_main=yes else ac_cv_lib_c_main=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_c_main" >&5 $as_echo "$ac_cv_lib_c_main" >&6; } if test "x$ac_cv_lib_c_main" = x""yes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBC 1 _ACEOF LIBS="-lc $LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lpthread" >&5 $as_echo_n "checking for main in -lpthread... " >&6; } if test "${ac_cv_lib_pthread_main+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lpthread $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_pthread_main=yes else ac_cv_lib_pthread_main=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_main" >&5 $as_echo "$ac_cv_lib_pthread_main" >&6; } if test "x$ac_cv_lib_pthread_main" = x""yes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBPTHREAD 1 _ACEOF LIBS="-lpthread $LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lz" >&5 $as_echo_n "checking for main in -lz... " >&6; } if test "${ac_cv_lib_z_main+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lz $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_z_main=yes else ac_cv_lib_z_main=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_z_main" >&5 $as_echo "$ac_cv_lib_z_main" >&6; } if test "x$ac_cv_lib_z_main" = x""yes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBZ 1 _ACEOF LIBS="-lz $LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -llzo2" >&5 $as_echo_n "checking for main in -llzo2... " >&6; } if test "${ac_cv_lib_lzo2_main+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-llzo2 $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_lzo2_main=yes else ac_cv_lib_lzo2_main=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_lzo2_main" >&5 $as_echo "$ac_cv_lib_lzo2_main" >&6; } if test "x$ac_cv_lib_lzo2_main" = x""yes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBLZO2 1 _ACEOF LIBS="-llzo2 $LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lbz2" >&5 $as_echo_n "checking for main in -lbz2... " >&6; } if test "${ac_cv_lib_bz2_main+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lbz2 $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_bz2_main=yes else ac_cv_lib_bz2_main=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_bz2_main" >&5 $as_echo "$ac_cv_lib_bz2_main" >&6; } if test "x$ac_cv_lib_bz2_main" = x""yes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBBZ2 1 _ACEOF LIBS="-lbz2 $LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -liconv" >&5 $as_echo_n "checking for main in -liconv... " >&6; } if test "${ac_cv_lib_iconv_main+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-liconv $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_iconv_main=yes else ac_cv_lib_iconv_main=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_iconv_main" >&5 $as_echo "$ac_cv_lib_iconv_main" >&6; } if test "x$ac_cv_lib_iconv_main" = x""yes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBICONV 1 _ACEOF LIBS="-liconv $LIBS" fi # Fundamental QDBM libraries { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lqdbm" >&5 $as_echo_n "checking for main in -lqdbm... " >&6; } if test "${ac_cv_lib_qdbm_main+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lqdbm $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_qdbm_main=yes else ac_cv_lib_qdbm_main=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_qdbm_main" >&5 $as_echo "$ac_cv_lib_qdbm_main" >&6; } if test "x$ac_cv_lib_qdbm_main" = x""yes; then : true else printf 'checking whether /usr/local/lib/libqdbm.* is... ' if ls /usr/local/lib/libqdbm.* > /dev/null 2>&1 then printf 'yes\n' else printf 'no\n' printf '#================================================================\n' 1>&2 printf '# WARNING: Install QDBM libraries before installation.\n' 1>&2 printf '#================================================================\n' 1>&2 fi fi #================================================================ # Generic Settings #================================================================ # Export variables # Targets ac_config_files="$ac_config_files Makefile" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then test "x$cache_file" != "x/dev/null" && { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} cat confcache >$cache_file else { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' # Transform confdefs.h into DEFS. # Protect against shell expansion while executing Makefile rules. # Protect against Makefile macro expansion. # # If the first sed substitution is executed (which looks for macros that # take arguments), then branch to the quote section. Otherwise, # look for a macro that doesn't take arguments. ac_script=' :mline /\\$/{ N s,\\\n,, b mline } t clear :clear s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g t quote s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g t quote b any :quote s/[ `~#$^&*(){}\\|;'\''"<>?]/\\&/g s/\[/\\&/g s/\]/\\&/g s/\$/$$/g H :any ${ g s/^\n// s/\n/ /g p } ' DEFS=`sed -n "$ac_script" confdefs.h` ac_libobjs= ac_ltlibobjs= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`$as_echo "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs : ${CONFIG_STATUS=./config.status} ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 $as_echo "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # as_fn_error ERROR [LINENO LOG_FD] # --------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with status $?, using 1 if that was 0. as_fn_error () { as_status=$?; test $as_status -eq 0 && as_status=1 if test "$3"; then as_lineno=${as_lineno-"$2"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $1" >&$3 fi $as_echo "$as_me: error: $1" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -p'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -p' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -p' fi else as_ln_s='cp -p' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi if test -x / >/dev/null 2>&1; then as_test_x='test -x' else if ls -dL / >/dev/null 2>&1; then as_ls_L_option=L else as_ls_L_option= fi as_test_x=' eval sh -c '\'' if test -d "$1"; then test -d "$1/."; else case $1 in #( -*)set "./$1";; esac; case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( ???[sx]*):;;*)false;;esac;fi '\'' sh ' fi as_executable_p=$as_test_x # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 ## ----------------------------------- ## ## Main body of $CONFIG_STATUS script. ## ## ----------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by qdbm-cgi $as_me 0.0.1, which was generated by GNU Autoconf 2.65. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ \`$as_me' instantiates files and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit --config print configuration, then exit -q, --quiet, --silent do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE Configuration files: $config_files Report bugs to the package provider." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ qdbm-cgi config.status 0.0.1 configured by $0, generated by GNU Autoconf 2.65, with options \\"\$ac_cs_config\\" Copyright (C) 2009 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) $as_echo "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) $as_echo "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --he | --h | --help | --hel | -h ) $as_echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) as_fn_error "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX $as_echo "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; *) as_fn_error "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= trap 'exit_status=$? { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error "cannot create a temporary directory in ." "$LINENO" 5 # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with `./config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=`echo X | tr X '\015'` # On cygwin, bash can eat \r inside `` if the user requested igncr. # But we know of no other shell where ac_cr would be empty at this # point, so we can use a bashism as a fallback. if test "x$ac_cr" = x; then eval ac_cr=\$\'\\r\' fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_num=`echo "$ac_subst_vars" | grep -c '$'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>"\$tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\)..*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\)..*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' >$CONFIG_STATUS || ac_write_fail=1 rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$tmp/subs1.awk" > "$tmp/subs.awk" \ || as_fn_error "could not setup config files machinery" "$LINENO" 5 _ACEOF # VPATH may cause trouble with some makes, so we remove $(srcdir), # ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=/{ s/:*\$(srcdir):*/:/ s/:*\${srcdir}:*/:/ s/:*@srcdir@:*/:/ s/^\([^=]*=[ ]*\):*/\1/ s/:*$// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" eval set X " :F $CONFIG_FILES " shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) as_fn_error "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || as_fn_error "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 $as_echo "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`$as_echo "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$tmp/stdin" \ || as_fn_error "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 $as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$tmp/subs.awk" >$tmp/out \ || as_fn_error "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } && { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined." >&5 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined." >&2;} rm -f "$tmp/stdin" case $ac_file in -) cat "$tmp/out" && rm -f "$tmp/out";; *) rm -f "$ac_file" && mv "$tmp/out" "$ac_file";; esac \ || as_fn_error "could not create $ac_file" "$LINENO" 5 ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || as_fn_error "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit $? fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi # END OF FILE qdbm-1.8.78/odtest.c0000644000175000017500000004301010610630126013203 0ustar mikiomikio/************************************************************************************************* * Test cases of Odeum * Copyright (C) 2000-2007 Mikio Hirabayashi * This file is part of QDBM, Quick Database Manager. * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU * Lesser General Public License as published by the Free Software Foundation; either version * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * You should have received a copy of the GNU Lesser General Public License along with QDBM; if * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. *************************************************************************************************/ #include #include #include #include #include #include #include #include #include #undef TRUE #define TRUE 1 /* boolean true */ #undef FALSE #define FALSE 0 /* boolean false */ #define DOCBUFSIZ 256 /* buffer for documents */ /* for RISC OS */ #if defined(__riscos__) || defined(__riscos) #include int __riscosify_control = __RISCOSIFY_NO_PROCESS; #endif /* global variables */ const char *progname; /* program name */ /* function prototypes */ int main(int argc, char **argv); void usage(void); int runwrite(int argc, char **argv); int runread(int argc, char **argv); int runcombo(int argc, char **argv); int runwicked(int argc, char **argv); int printfflush(const char *format, ...); void pdperror(const char *name); int myrand(void); ODDOC *makedoc(int id, int wnum, int pnum); int dowrite(const char *name, int dnum, int wnum, int pnum, int ibnum, int idnum, int cbnum, int csiz); int doread(const char *name); int docombo(const char *name); int dowicked(const char *name, int dnum); /* main routine */ int main(int argc, char **argv){ char *env; int rv; cbstdiobin(); if((env = getenv("QDBMDBGFD")) != NULL) dpdbgfd = atoi(env); progname = argv[0]; if(argc < 2) usage(); rv = 0; if(!strcmp(argv[1], "write")){ rv = runwrite(argc, argv); } else if(!strcmp(argv[1], "read")){ rv = runread(argc, argv); } else if(!strcmp(argv[1], "combo")){ rv = runcombo(argc, argv); } else if(!strcmp(argv[1], "wicked")){ rv = runwicked(argc, argv); } else { usage(); } return 0; } /* print the usage and exit */ void usage(void){ fprintf(stderr, "%s: test cases for Odeum\n", progname); fprintf(stderr, "\n"); fprintf(stderr, "usage:\n"); fprintf(stderr, " %s write [-tune ibnum idnum cbnum csiz] name dnum wnum pnum\n", progname); fprintf(stderr, " %s read name\n", progname); fprintf(stderr, " %s combo name\n", progname); fprintf(stderr, " %s wicked name dnum\n", progname); fprintf(stderr, "\n"); exit(1); } /* parse arguments of write command */ int runwrite(int argc, char **argv){ char *name, *dstr, *wstr, *pstr; int i, dnum, wnum, pnum, ibnum, idnum, cbnum, csiz, rv; name = NULL; dstr = NULL; wstr = NULL; pstr = NULL; dnum = 0; wnum = 0; pnum = 0; ibnum = -1; idnum = -1; cbnum = -1; csiz = -1; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ if(!strcmp(argv[i], "-tune")){ if(++i >= argc) usage(); ibnum = atoi(argv[i]); if(++i >= argc) usage(); idnum = atoi(argv[i]); if(++i >= argc) usage(); cbnum = atoi(argv[i]); if(++i >= argc) usage(); csiz = atoi(argv[i]); } else { usage(); } } else if(!name){ name = argv[i]; } else if(!dstr){ dstr = argv[i]; } else if(!wstr){ wstr = argv[i]; } else if(!pstr){ pstr = argv[i]; } else { usage(); } } if(!name || !dstr || !wstr || !pstr) usage(); dnum = atoi(dstr); wnum = atoi(wstr); pnum = atoi(pstr); if(dnum < 1 || wnum < 1 || pnum < 1) usage(); rv = dowrite(name, dnum, wnum, pnum, ibnum, idnum, cbnum, csiz); return rv; } /* parse arguments of read command */ int runread(int argc, char **argv){ char *name; int i, rv; name = NULL; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ usage(); } else if(!name){ name = argv[i]; } else { usage(); } } if(!name) usage(); rv = doread(name); return rv; } /* parse arguments of combo command */ int runcombo(int argc, char **argv){ char *name; int i, rv; name = NULL; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ usage(); } else if(!name){ name = argv[i]; } else { usage(); } } if(!name) usage(); rv = docombo(name); return rv; } /* parse arguments of wicked command */ int runwicked(int argc, char **argv){ char *name, *dstr; int i, dnum, rv; name = NULL; dstr = NULL; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ usage(); } else if(!name){ name = argv[i]; } else if(!dstr){ dstr = argv[i]; } else { usage(); } } if(!name || !dstr) usage(); dnum = atoi(dstr); if(dnum < 1) usage(); rv = dowicked(name, dnum); return rv; } /* print formatted string and flush the buffer */ int printfflush(const char *format, ...){ va_list ap; int rv; va_start(ap, format); rv = vprintf(format, ap); if(fflush(stdout) == EOF) rv = -1; va_end(ap); return rv; } /* print an error message */ void pdperror(const char *name){ fprintf(stderr, "%s: %s: %s\n", progname, name, dperrmsg(dpecode)); } /* pseudo random number generator */ int myrand(void){ static int cnt = 0; if(cnt == 0) srand(time(NULL)); return (rand() * rand() + (rand() >> (sizeof(int) * 4)) + (cnt++)) & INT_MAX; } /* create a document */ ODDOC *makedoc(int id, int wnum, int pnum){ ODDOC *doc; char buf[DOCBUFSIZ]; int i; sprintf(buf, "%08d", id); doc = oddocopen(buf); oddocaddattr(doc, "title", buf); oddocaddattr(doc, "author", buf); oddocaddattr(doc, "date", buf); for(i = 0; i < wnum; i++){ sprintf(buf, "%08d", myrand() % pnum); oddocaddword(doc, buf, buf); } return doc; } /* perform write command */ int dowrite(const char *name, int dnum, int wnum, int pnum, int ibnum, int idnum, int cbnum, int csiz){ ODEUM *odeum; ODDOC *doc; int i, err; printfflush("\n name=%s dnum=%d wnum=%d pnum=%d" " ibnum=%d idnum=%d cbnum=%d csiz=%d\n\n", name, dnum, wnum, pnum, ibnum, idnum, cbnum, csiz); /* open a database */ if(ibnum > 0) odsettuning(ibnum, idnum, cbnum, csiz); if(!(odeum = odopen(name, OD_OWRITER | OD_OCREAT | OD_OTRUNC))){ pdperror(name); return 1; } err = FALSE; /* loop for each document */ for(i = 1; i <= dnum; i++){ /* store a document */ doc = makedoc(i, wnum, pnum); if(!odput(odeum, doc, -1, FALSE)){ pdperror(name); oddocclose(doc); err = TRUE; break; } oddocclose(doc); /* print progression */ if(dnum > 250 && i % (dnum / 250) == 0){ putchar('.'); fflush(stdout); if(i == dnum || i % (dnum / 10) == 0){ printfflush(" (%08d)\n", i); } } } /* close the database */ if(!odclose(odeum)){ pdperror(name); return 1; } if(!err) printfflush("ok\n\n"); return err ? 1 : 0; } /* perform read command */ int doread(const char *name){ ODEUM *odeum; ODDOC *doc; char buf[DOCBUFSIZ]; int i, dnum, err; printfflush("\n name=%s\n\n", name); /* open a database */ if(!(odeum = odopen(name, OD_OREADER))){ pdperror(name); return 1; } /* get the number of documents */ dnum = oddnum(odeum); err = FALSE; /* loop for each document */ for(i = 1; i <= dnum; i++){ /* retrieve a document */ sprintf(buf, "%08d", i); if(!(doc = odget(odeum, buf))){ pdperror(name); err = TRUE; break; } oddocclose(doc); /* print progression */ if(dnum > 250 && i % (dnum / 250) == 0){ putchar('.'); fflush(stdout); if(i == dnum || i % (dnum / 10) == 0){ printfflush(" (%08d)\n", i); } } } /* close the database */ if(!odclose(odeum)){ pdperror(name); return 1; } if(!err) printfflush("ok\n\n"); return err ? 1 : 0; } /* perform combo command */ int docombo(const char *name){ ODEUM *odeum; ODDOC *doc; const CBLIST *nwords, *awords; CBLIST *tawords, *tnwords, *oawords; ODPAIR *pairs; const char *asis; char buf[DOCBUFSIZ], *normal; int i, j, pnum; printfflush("\n name=%s\n\n", name); printfflush("Creating a database with ... "); if(!(odeum = odopen(name, OD_OWRITER | OD_OCREAT | OD_OTRUNC))){ pdperror(name); return 1; } printfflush("ok\n"); printfflush("Adding 20 documents including about 200 words ... "); for(i = 1; i <= 20; i++){ sprintf(buf, "%08d", i); doc = makedoc(i, 120 + myrand() % 160, myrand() % 500 + 500); if(!odput(odeum, doc, 180 + myrand() % 40, FALSE)){ pdperror(name); oddocclose(doc); odclose(odeum); return 1; } oddocclose(doc); } printfflush("ok\n"); printfflush("Checking documents ... "); for(i = 1; i <= 20; i++){ sprintf(buf, "%08d", i); if(!(doc = odget(odeum, buf))){ pdperror(name); return 1; } nwords = oddocnwords(doc); awords = oddocawords(doc); if(!oddocuri(doc) || !oddocgetattr(doc, "title") || cblistnum(nwords) != cblistnum(awords)){ fprintf(stderr, "%s: %s: invalid document\n", progname, name); oddocclose(doc); odclose(odeum); return 1; } for(j = 0; j < cblistnum(nwords); j++){ if(strcmp(cblistval(nwords, j, NULL), cblistval(nwords, j, NULL))){ fprintf(stderr, "%s: %s: invalid words\n", progname, name); oddocclose(doc); odclose(odeum); return 1; } } oddocclose(doc); } printfflush("ok\n"); printfflush("Syncing the database ... "); if(!odsync(odeum)){ pdperror(name); odclose(odeum); return 1; } printfflush("ok\n"); printfflush("Overwriting 1 - 10 documents ... "); for(i = 1; i <= 10; i++){ sprintf(buf, "%08d", i); doc = makedoc(i, 120 + myrand() % 160, myrand() % 500 + 500); if(!odput(odeum, doc, 180 + myrand() % 40, TRUE)){ pdperror(name); oddocclose(doc); odclose(odeum); return 1; } oddocclose(doc); } printfflush("ok\n"); printfflush("Deleting 11 - 20 documents ... "); for(i = 11; i <= 20; i++){ sprintf(buf, "%08d", i); if(!odout(odeum, buf)){ pdperror(name); odclose(odeum); return 1; } } printfflush("ok\n"); printfflush("Checking documents ... "); for(i = 1; i <= 10; i++){ sprintf(buf, "%08d", i); if(!(doc = odget(odeum, buf))){ pdperror(name); return 1; } nwords = oddocnwords(doc); awords = oddocawords(doc); if(!oddocuri(doc) || !oddocgetattr(doc, "title") || cblistnum(nwords) != cblistnum(awords)){ fprintf(stderr, "%s: %s: invalid document\n", progname, name); oddocclose(doc); odclose(odeum); return 1; } for(j = 0; j < cblistnum(nwords); j++){ if(strcmp(cblistval(nwords, j, NULL), cblistval(nwords, j, NULL))){ fprintf(stderr, "%s: %s: invalid words\n", progname, name); oddocclose(doc); odclose(odeum); return 1; } } oddocclose(doc); } if(oddnum(odeum) != 10){ fprintf(stderr, "%s: %s: invalid document number\n", progname, name); odclose(odeum); return 1; } printfflush("ok\n"); printfflush("Optimizing the database ... "); if(!odoptimize(odeum)){ pdperror(name); odclose(odeum); return 1; } printfflush("ok\n"); printfflush("Adding 10 documents including about 200 words ... "); for(i = 11; i <= 20; i++){ sprintf(buf, "%08d", i); doc = makedoc(i, 120 + myrand() % 160, myrand() % 500 + 500); if(!odput(odeum, doc, 180 + myrand() % 40, FALSE)){ pdperror(name); oddocclose(doc); odclose(odeum); return 1; } oddocclose(doc); } printfflush("ok\n"); printfflush("Deleting 6 - 15 documents ... "); for(i = 6; i <= 15; i++){ sprintf(buf, "%08d", i); if(!odout(odeum, buf)){ pdperror(name); odclose(odeum); return 1; } } printfflush("ok\n"); printfflush("Retrieving documents 100 times ... "); for(i = 1; i <= 100; i++){ sprintf(buf, "%08d", myrand() % 1000 + 1); if((pairs = odsearch(odeum, buf, -1, &pnum)) != NULL){ for(j = 0; j < pnum; j++){ if((doc = odgetbyid(odeum, pairs[j].id)) != NULL){ oddocclose(doc); } else if(dpecode != DP_ENOITEM){ pdperror(name); odclose(odeum); return 1; } } free(pairs); } else if(dpecode != DP_ENOITEM){ pdperror(name); odclose(odeum); return 1; } } printfflush("ok\n"); printfflush("Analyzing text ... "); tawords = cblistopen(); tnwords = cblistopen(); odanalyzetext(odeum, "I'd like to ++see++ Mr. X-men tomorrow.", tawords, tnwords); odanalyzetext(odeum, "=== :-) SMILE . @ . SAD :-< ===", tawords, tnwords); for(i = 0; i < DOCBUFSIZ - 1; i++){ buf[i] = myrand() % 255 + 1; } buf[DOCBUFSIZ-1] = '\0'; cblistclose(tnwords); cblistclose(tawords); for(i = 0; i < 1000; i++){ for(j = 0; j < DOCBUFSIZ - 1; j++){ if((j + 1) % 32 == 0){ buf[j] = ' '; } else { buf[j] = myrand() % 255 + 1; } } buf[DOCBUFSIZ-1] = '\0'; tawords = cblistopen(); tnwords = cblistopen(); odanalyzetext(odeum, buf, tawords, tnwords); oawords = odbreaktext(buf); if(cblistnum(tawords) != cblistnum(oawords) || cblistnum(tnwords) != cblistnum(oawords)){ fprintf(stderr, "%s: %s: invalid analyzing\n", progname, name); cblistclose(oawords); cblistclose(tnwords); cblistclose(tawords); odclose(odeum); return 1; } for(j = 0; j < cblistnum(oawords); j++){ asis = cblistval(oawords, j, NULL); normal = odnormalizeword(asis); if(strcmp(asis, cblistval(oawords, j, NULL)) || strcmp(normal, cblistval(tnwords, j, NULL))){ fprintf(stderr, "%s: %s: invalid analyzing\n", progname, name); free(normal); cblistclose(oawords); cblistclose(tnwords); cblistclose(tawords); odclose(odeum); return 1; } free(normal); } cblistclose(oawords); cblistclose(tnwords); cblistclose(tawords); } printfflush("ok\n"); printfflush("Closing the database ... "); if(!odclose(odeum)){ pdperror(name); return 1; } printfflush("ok\n"); printfflush("all ok\n\n"); return 0; } /* perform wicked command */ int dowicked(const char *name, int dnum){ ODEUM *odeum; ODDOC *doc; ODPAIR *pairs; char buf[DOCBUFSIZ]; int i, j, pnum, err; printfflush("\n name=%s dnum=%d\n\n", name, dnum); err = FALSE; if(!(odeum = odopen(name, OD_OWRITER | OD_OCREAT | OD_OTRUNC))){ pdperror(name); return 1; } for(i = 1; i <= dnum; i++){ switch(myrand() % 8){ case 1: putchar('K'); doc = makedoc(myrand() % dnum + 1, myrand() % 10 + 10, myrand() % dnum + 500); if(!odput(odeum, doc, 5, FALSE) && dpecode != DP_EKEEP) err = TRUE; oddocclose(doc); break; case 3: putchar('D'); if(!odoutbyid(odeum, myrand() % dnum + 1) && dpecode != DP_ENOITEM) err = TRUE; break; case 4: putchar('R'); sprintf(buf, "%08d", myrand() % (dnum + 500) + 1); if((pairs = odsearch(odeum, buf, 5, &pnum)) != NULL){ if(myrand() % 5 == 0){ for(j = 0; j < pnum; j++){ if((doc = odgetbyid(odeum, pairs[j].id)) != NULL){ oddocclose(doc); } else if(dpecode != DP_ENOITEM){ err = TRUE; break; } } } free(pairs); } else if(dpecode != DP_ENOITEM){ err = TRUE; } break; default: putchar('O'); doc = makedoc(myrand() % dnum + 1, myrand() % 10 + 10, myrand() % dnum + 500); if(!odput(odeum, doc, 5, TRUE)) err = TRUE; oddocclose(doc); break; } if(i % 50 == 0) printfflush(" (%08d)\n", i); if(err){ pdperror(name); break; } } if(!odoptimize(odeum)){ pdperror(name); err = TRUE; } for(i = 1; i <= dnum; i++){ doc = makedoc(i, 5, 5); if(!odput(odeum, doc, 5, FALSE) && dpecode != DP_EKEEP){ pdperror(name); oddocclose(doc); err = TRUE; break; } oddocclose(doc); putchar(':'); if(i % 50 == 0) printfflush(" (%08d)\n", i); } if(!odoptimize(odeum)){ pdperror(name); err = TRUE; } for(i = 1; i <= dnum; i++){ sprintf(buf, "%08d", i); if(!(doc = odget(odeum, buf))){ pdperror(name); err = TRUE; break; } oddocclose(doc); putchar('='); if(i % 50 == 0) printfflush(" (%08d)\n", i); } if(!oditerinit(odeum)){ pdperror(name); err = TRUE; } for(i = 1; i <= dnum; i++){ if(!(doc = oditernext(odeum))){ pdperror(name); err = TRUE; break; } oddocclose(doc); putchar('@'); if(i % 50 == 0) printfflush(" (%08d)\n", i); } if(!odclose(odeum)){ pdperror(name); return 1; } if(!err) printfflush("ok\n\n"); return 0; } /* END OF FILE */ qdbm-1.8.78/configure.in0000644000175000017500000001611210733145330014055 0ustar mikiomikio# Source of configuration for QDBM #================================================================ # Generic Settings #================================================================ # Targets AC_INIT(qdbm, 1.8.78) # Export variables LIBVER=14 LIBREV=14 TARGETS="all" MYDEFS="" MYOPTS="" MGWLIBS="" LD="ld" AR="ar" # Building paths pathtmp="$PATH" PATH="$HOME/bin:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin" PATH="$PATH:/usr/ccs/bin:/usr/ucb:/usr/xpg4/bin:/usr/xpg6/bin:$pathtmp" LIBRARY_PATH="$HOME/lib:/usr/local/lib:$LIBRARY_PATH" LD_LIBRARY_PATH="$HOME/lib:/usr/local/lib:$LD_LIBRARY_PATH" CPATH="$HOME/include:/usr/local/include:$CPATH" export PATH LIBRARY_PATH LD_LIBRARY_PATH CPATH #================================================================ # Options #================================================================ # Internal variables enables="" ispthread="" iszlib="" isiconv="" isnowarn="" # Debug mode AC_ARG_ENABLE(debug, AC_HELP_STRING([--enable-debug], [build for debugging])) if test "$enable_debug" = "yes" then TARGETS="debug" enables="$enables (debug)" fi # Developping mode AC_ARG_ENABLE(devel, AC_HELP_STRING([--enable-devel], [build for development])) if test "$enable_devel" = "yes" then TARGETS="devel" enables="$enables (devel)" fi # Stable mode AC_ARG_ENABLE(stable, AC_HELP_STRING([--enable-stable], [build for stable release])) if test "$enable_stable" = "yes" then TARGETS="stable" enables="$enables (stable)" fi # Enable POSIX thread AC_ARG_ENABLE(pthread, AC_HELP_STRING([--enable-pthread], [use POSIX thread and make APIs thread-safe])) if test "$enable_pthread" = "yes" then MYDEFS="$MYDEFS -DMYPTHREAD" enables="$enables (pthread)" ispthread="yes" fi # Disable file locking AC_ARG_ENABLE(lock, AC_HELP_STRING([--disable-lock], [build for environments without file locking])) if test "$enable_lock" = "no" then MYDEFS="$MYDEFS -DMYNOLOCK" enables="$enables (no-lock)" fi # Disable memory mapping AC_ARG_ENABLE(mmap, AC_HELP_STRING([--disable-mmap], [build for environments without memory mapping])) if test "$enable_mmap" = "no" then MYDEFS="$MYDEFS -DMYNOMMAP" enables="$enables (no-mmap)" fi # Enable ZLIB compression AC_ARG_ENABLE(zlib, AC_HELP_STRING([--enable-zlib], [feature ZLIB for B+ tree and inverted index])) if test "$enable_zlib" = "yes" then MYDEFS="$MYDEFS -DMYZLIB" MGWLIBS="-lz $MGWLIBS" enables="$enables (zlib)" iszlib="yes" fi # Enable LZO compression AC_ARG_ENABLE(lzo, AC_HELP_STRING([--enable-lzo], [feature LZO for B+ tree and inverted index])) if test "$enable_lzo" = "yes" then MYDEFS="$MYDEFS -DMYLZO" MGWLIBS="-llzo2 $MGWLIBS" enables="$enables (lzo)" islzo="yes" fi # Enable BZIP2 compression AC_ARG_ENABLE(bzip, AC_HELP_STRING([--enable-bzip], [feature BZIP2 for B+ tree and inverted index])) if test "$enable_bzip" = "yes" then MYDEFS="$MYDEFS -DMYBZIP" MGWLIBS="-lbz2 $MGWLIBS" enables="$enables (bzip)" isbzip="yes" fi # Enable ICONV utilities AC_ARG_ENABLE(iconv, AC_HELP_STRING([--enable-iconv], [feature ICONV utilities])) if test "$enable_iconv" = "yes" then MYDEFS="$MYDEFS -DMYICONV" MGWLIBS="-liconv $MGWLIBS" enables="$enables (iconv)" isiconv="yes" fi # No warning configuration AC_ARG_ENABLE(warn, AC_HELP_STRING([--disable-warn], [hide warnings in the configuration])) if test "$enable_warn" = "no" then isnowarn="yes" fi # Messages printf '#================================================================\n' printf '# Configuring QDBM version %s%s.\n' "$PACKAGE_VERSION" "$enables" printf '#================================================================\n' #================================================================ # Checking Commands to Build with #================================================================ # C compiler AC_PROG_CC if test "$GCC" != "yes" then if test "$isnowarn" != "yes" then printf '#================================================================\n' 1>&2 printf '# WARNING: GCC is required to build this package.\n' 1>&2 printf '#================================================================\n' 1>&2 fi fi if uname | egrep -i 'Linux' > /dev/null 2>&1 && uname -m | egrep '(x|i)(3|4|5|6|7|8|9)?86' > /dev/null 2>&1 then MYOPTS="-minline-all-stringops" fi if uname | egrep -i 'SunOS' > /dev/null 2>&1 then MYOPTS="-O1 -fno-omit-frame-pointer -fno-force-addr" fi if uname | egrep -i 'BSD' > /dev/null 2>&1 then MYOPTS="-O1 -fno-omit-frame-pointer -fno-force-addr" fi if gcc --version | egrep -i '^2\.(8|9)' > /dev/null 2>&1 then MYOPTS="-O1 -fno-omit-frame-pointer -fno-force-addr" fi # Linker printf 'checking for ld... ' if which ld | grep '/ld$' > /dev/null 2>&1 then LD=`which ld` printf '%s\n' "$LD" else printf 'no\n' if test "$isnowarn" != "yes" then printf '#================================================================\n' 1>&2 printf '# WARNING: ld is not found in PATH.\n' 1>&2 printf '#================================================================\n' 1>&2 fi fi # Archiver printf 'checking for ar... ' if which ar | grep '/ar$' > /dev/null 2>&1 then AR=`which ar` printf '%s\n' "$AR" else printf 'no\n' if test "$isnowarn" != "yes" then printf '#================================================================\n' 1>&2 printf '# WARNING: ar is not found in PATH.\n' 1>&2 printf '#================================================================\n' 1>&2 fi fi #================================================================ # Checking Libraries #================================================================ # Underlying libraries AC_CHECK_LIB(c, main) # for pthread if test "$ispthread" = "yes" then AC_CHECK_LIB(pthread, main) fi # for zlib if test "$iszlib" = "yes" then AC_CHECK_LIB(z, main) fi # for lzo if test "$islzo" = "yes" then AC_CHECK_LIB(lzo2, main) fi # for bzip if test "$isbzip" = "yes" then AC_CHECK_LIB(bz2, main) fi # for iconv if test "$isiconv" = "yes" then AC_CHECK_LIB(iconv, main) fi # For old BSDs if test "$ispthread" = "yes" && uname -a | grep BSD > /dev/null && test -f /usr/lib/libc_r.a && test ! -f /usr/lib/libpthread.a then LIBS=`printf '%s' "$LIBS" | sed 's/-lc/-lc_r/g'` fi # Duplication of QDBM for C AC_CHECK_LIB(qdbm, main, if test "$isnowarn" != "yes" then printf '#================================================================\n' 1>&2 printf '# WARNING: The existing library was detected.\n' 1>&2 printf '#================================================================\n' 1>&2 fi ) #================================================================ # Generic Settings #================================================================ # Export variables AC_SUBST(LIBVER) AC_SUBST(LIBREV) AC_SUBST(TARGETS) AC_SUBST(MYDEFS) AC_SUBST(MYOPTS) AC_SUBST(MGWLIBS) AC_SUBST(LD) AC_SUBST(AR) AC_SUBST(CPPFLAGS) AC_SUBST(LDFLAGS) # Targets AC_OUTPUT(Makefile LTmakefile qdbm.spec qdbm.pc) # Messages printf '#================================================================\n' printf '# Ready to make.\n' printf '#================================================================\n' # END OF FILE qdbm-1.8.78/cbcodec.c0000644000175000017500000006471710610627747013323 0ustar mikiomikio/************************************************************************************************* * Popular encoders and decoders * Copyright (C) 2000-2007 Mikio Hirabayashi * This file is part of QDBM, Quick Database Manager. * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU * Lesser General Public License as published by the Free Software Foundation; either version * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * You should have received a copy of the GNU Lesser General Public License along with QDBM; if * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. *************************************************************************************************/ #include #include #include #include #include #undef TRUE #define TRUE 1 /* boolean true */ #undef FALSE #define FALSE 0 /* boolean false */ #define DEFCODE "UTF-8" /* default encoding */ /* for RISC OS */ #if defined(__riscos__) || defined(__riscos) #include int __riscosify_control = __RISCOSIFY_NO_PROCESS; #endif /* global variables */ const char *progname; /* program name */ /* function prototypes */ int main(int argc, char **argv); void usage(void); char *readstdin(int *sp); int runurl(int argc, char **argv); int runbase(int argc, char **argv); int runquote(int argc, char **argv); int runmime(int argc, char **argv); int runcsv(int argc, char **argv); int runxml(int argc, char **argv); int runzlib(int argc, char **argv); int runlzo(int argc, char **argv); int runbzip(int argc, char **argv); int runiconv(int argc, char **argv); int rundate(int argc, char **argv); void shouucsmap(void); /* main routine */ int main(int argc, char **argv){ int rv; cbstdiobin(); progname = argv[0]; if(argc < 2) usage(); rv = 0; if(!strcmp(argv[1], "url")){ rv = runurl(argc, argv); } else if(!strcmp(argv[1], "base")){ rv = runbase(argc, argv); } else if(!strcmp(argv[1], "quote")){ rv = runquote(argc, argv); } else if(!strcmp(argv[1], "mime")){ rv = runmime(argc, argv); } else if(!strcmp(argv[1], "csv")){ rv = runcsv(argc, argv); } else if(!strcmp(argv[1], "xml")){ rv = runxml(argc, argv); } else if(!strcmp(argv[1], "zlib")){ rv = runzlib(argc, argv); } else if(!strcmp(argv[1], "lzo")){ rv = runlzo(argc, argv); } else if(!strcmp(argv[1], "bzip")){ rv = runbzip(argc, argv); } else if(!strcmp(argv[1], "iconv")){ rv = runiconv(argc, argv); } else if(!strcmp(argv[1], "date")){ rv = rundate(argc, argv); } else { usage(); } return rv; } /* print the usage and exit */ void usage(void){ char *tmp; int tsiz; fprintf(stderr, "%s: popular encoders and decoders\n", progname); fprintf(stderr, "\n"); fprintf(stderr, "usage:\n"); fprintf(stderr, " %s url [-d] [-br] [-rs base target] [-l] [-e expr] [file]\n", progname); fprintf(stderr, " %s base [-d] [-l] [-c num] [-e expr] [file]\n", progname); fprintf(stderr, " %s quote [-d] [-l] [-c num] [-e expr] [file]\n", progname); fprintf(stderr, " %s mime [-d] [-hd] [-bd] [-part num] [-l] [-ec code] [-qp] [-dc] [-e expr]" " [file]\n", progname); fprintf(stderr, " %s csv [-d] [-t] [-l] [-e expr] [-html] [file]\n", progname); fprintf(stderr, " %s xml [-d] [-p] [-l] [-e expr] [-tsv] [file]\n", progname); if((tmp = cbdeflate("", 0, &tsiz)) != NULL){ fprintf(stderr, " %s zlib [-d] [-gz] [-crc] [file]\n", progname); free(tmp); } if((tmp = cblzoencode("", 0, &tsiz)) != NULL){ fprintf(stderr, " %s lzo [-d] [file]\n", progname); free(tmp); } if((tmp = cbbzencode("", 0, &tsiz)) != NULL){ fprintf(stderr, " %s bzip [-d] [file]\n", progname); free(tmp); } if((tmp = cbiconv("", 0, "US-ASCII", "US-ASCII", NULL, NULL)) != NULL){ fprintf(stderr, " %s iconv [-ic code] [-oc code] [-ol ltype] [-cn] [-wc] [-um] [file]\n", progname); free(tmp); } fprintf(stderr, " %s date [-wf] [-rf] [-utc] [str]\n", progname); fprintf(stderr, "\n"); exit(1); } /* read the standard input */ char *readstdin(int *sp){ char *buf; int i, blen, c; blen = 256; buf = cbmalloc(blen); for(i = 0; (c = getchar()) != EOF; i++){ if(i >= blen - 1) buf = cbrealloc(buf, blen *= 2); buf[i] = c; } buf[i] = '\0'; if(sp) *sp = i; return buf; } /* parse arguments of url command */ int runurl(int argc, char **argv){ CBMAP *map; int i, size, dec, br, line; const char *val; char *base, *target, *expr, *file, *buf, *res; dec = FALSE; br = FALSE; line = FALSE; base = NULL; target = NULL; expr = NULL; file = NULL; for(i = 2; i < argc; i++){ if(!file && argv[i][0] == '-'){ if(!strcmp(argv[i], "-d")){ dec = TRUE; } else if(!strcmp(argv[i], "-br")){ br = TRUE; } else if(!strcmp(argv[i], "-rs")){ if(++i >= argc) usage(); base = argv[i]; if(++i >= argc) usage(); target = argv[i]; } else if(!strcmp(argv[i], "-l")){ line = TRUE; } else if(!strcmp(argv[i], "-e")){ if(++i >= argc) usage(); expr = argv[i]; } else { usage(); } } else if(!file){ file = argv[i]; } else { usage(); } } buf = NULL; if(base){ size = strlen(base); buf = cbmemdup(base, size); } else if(expr){ size = strlen(expr); buf = cbmemdup(expr, size); } else if(file){ if(!(buf = cbreadfile(file, &size))){ fprintf(stderr, "%s: %s: cannot open\n", progname, file); return 1; } } else { buf = readstdin(&size); } if(target){ res = cburlresolve(base, target); printf("%s", res); free(res); } else if(br){ map = cburlbreak(buf); if((val = cbmapget(map, "self", -1, NULL))) printf("self\t%s\n", val); if((val = cbmapget(map, "scheme", -1, NULL))) printf("scheme\t%s\n", val); if((val = cbmapget(map, "host", -1, NULL))) printf("host\t%s\n", val); if((val = cbmapget(map, "port", -1, NULL))) printf("port\t%s\n", val); if((val = cbmapget(map, "authority", -1, NULL))) printf("authority\t%s\n", val); if((val = cbmapget(map, "path", -1, NULL))) printf("path\t%s\n", val); if((val = cbmapget(map, "file", -1, NULL))) printf("file\t%s\n", val); if((val = cbmapget(map, "query", -1, NULL))) printf("query\t%s\n", val); if((val = cbmapget(map, "fragment", -1, NULL))) printf("fragment\t%s\n", val); cbmapclose(map); } else if(dec){ res = cburldecode(buf, &size); for(i = 0; i < size; i++){ putchar(res[i]); } free(res); } else { res = cburlencode(buf, size); for(i = 0; res[i] != '\0'; i++){ putchar(res[i]); } free(res); } if(line) putchar('\n'); free(buf); return 0; } /* parse arguments of base command */ int runbase(int argc, char **argv){ int i, ci, size, dec, line, cols; char *expr, *file, *buf, *res; dec = FALSE; line = FALSE; cols = -1; expr = NULL; file = NULL; for(i = 2; i < argc; i++){ if(!file && argv[i][0] == '-'){ if(!strcmp(argv[i], "-d")){ dec = TRUE; } else if(!strcmp(argv[i], "-l")){ line = TRUE; } else if(!strcmp(argv[i], "-c")){ if(++i >= argc) usage(); cols = atoi(argv[i]); } else if(!strcmp(argv[i], "-e")){ if(++i >= argc) usage(); expr = argv[i]; } else { usage(); } } else if(!file){ file = argv[i]; } else { usage(); } } buf = NULL; if(expr){ size = strlen(expr); buf = cbmemdup(expr, size); } else if(file){ if(!(buf = cbreadfile(file, &size))){ fprintf(stderr, "%s: %s: cannot open\n", progname, file); return 1; } } else { buf = readstdin(&size); } if(dec){ res = cbbasedecode(buf, &size); for(i = 0; i < size; i++){ putchar(res[i]); } free(res); } else { res = cbbaseencode(buf, size); ci = 0; for(i = 0; res[i] != '\0'; i++){ if(cols > 0 && ci >= cols){ putchar('\n'); ci = 0; } putchar(res[i]); ci++; } free(res); } if(line) putchar('\n'); free(buf); return 0; } /* parse arguments of quote command */ int runquote(int argc, char **argv){ int i, ci, size, dec, line, cols; char *expr, *file, *buf, *res; dec = FALSE; line = FALSE; cols = -1; expr = NULL; file = NULL; for(i = 2; i < argc; i++){ if(!file && argv[i][0] == '-'){ if(!strcmp(argv[i], "-d")){ dec = TRUE; } else if(!strcmp(argv[i], "-l")){ line = TRUE; } else if(!strcmp(argv[i], "-c")){ if(++i >= argc) usage(); cols = atoi(argv[i]); } else if(!strcmp(argv[i], "-e")){ if(++i >= argc) usage(); expr = argv[i]; } else { usage(); } } else if(!file){ file = argv[i]; } else { usage(); } } buf = NULL; if(expr){ size = strlen(expr); buf = cbmemdup(expr, size); } else if(file){ if(!(buf = cbreadfile(file, &size))){ fprintf(stderr, "%s: %s: cannot open\n", progname, file); return 1; } } else { buf = readstdin(&size); } if(dec){ res = cbquotedecode(buf, &size); for(i = 0; i < size; i++){ putchar(res[i]); } free(res); } else { res = cbquoteencode(buf, size); ci = 0; for(i = 0; res[i] != '\0'; i++){ if(cols > 0 && (ci >= cols || (ci >= cols - 2 && res[i] == '='))){ printf("=\n"); ci = 0; } if(res[i] == '\r' || res[i] == '\n') ci = 0; putchar(res[i]); ci++; } free(res); } if(line) putchar('\n'); free(buf); return 0; } /* parse arguments of mime command */ int runmime(int argc, char **argv){ CBMAP *attrs; CBLIST *parts; int i, size, dec, line, qp, dc, hd, bd, pnum, rsiz, bsiz; const char *key, *body; char *code, *expr, *file, *buf, *res, renc[64]; dec = FALSE; hd = FALSE; bd = FALSE; pnum = 0; line = FALSE; dc = FALSE; qp = FALSE; code = NULL; expr = NULL; file = NULL; for(i = 2; i < argc; i++){ if(!file && argv[i][0] == '-'){ if(!strcmp(argv[i], "-d")){ dec = TRUE; } else if(!strcmp(argv[i], "-hd")){ hd = TRUE; } else if(!strcmp(argv[i], "-bd")){ bd = TRUE; } else if(!strcmp(argv[i], "-part")){ if(++i >= argc) usage(); pnum = atoi(argv[i]); } else if(!strcmp(argv[i], "-l")){ line = TRUE; } else if(!strcmp(argv[i], "-ec")){ if(++i >= argc) usage(); code = argv[i]; } else if(!strcmp(argv[i], "-qp")){ qp = TRUE; } else if(!strcmp(argv[i], "-dc")){ dc = TRUE; } else if(!strcmp(argv[i], "-e")){ if(++i >= argc) usage(); expr = argv[i]; } else { usage(); } } else if(!file){ file = argv[i]; } else { usage(); } } buf = NULL; if(expr){ size = strlen(expr); buf = cbmemdup(expr, size); } else if(file){ if(!(buf = cbreadfile(file, &size))){ fprintf(stderr, "%s: %s: cannot open\n", progname, file); return 1; } } else { buf = readstdin(&size); } if(hd || bd || pnum > 0){ attrs = cbmapopen(); res = cbmimebreak(buf, size, attrs, &rsiz); if(pnum > 0){ parts = NULL; if(!(key = cbmapget(attrs, "TYPE", -1, NULL)) || !cbstrfwimatch(key, "multipart/") || !(key = cbmapget(attrs, "BOUNDARY", -1, NULL)) || !(parts = cbmimeparts(res, rsiz, key)) || cblistnum(parts) < pnum){ fprintf(stderr, "%s: not multipart or no such part\n", progname); if(parts) cblistclose(parts); free(res); cbmapclose(attrs); free(buf); return 1; } body = cblistval(parts, pnum - 1, &bsiz); for(i = 0; i < bsiz; i++){ putchar(body[i]); } cblistclose(parts); } else if(hd){ cbmapiterinit(attrs); while((key = cbmapiternext(attrs, NULL)) != NULL){ printf("%s\t%s\n", key, cbmapget(attrs, key, -1, NULL)); } } else { for(i = 0; i < rsiz; i++){ putchar(res[i]); } } free(res); cbmapclose(attrs); } else if(dec){ res = cbmimedecode(buf, renc); printf("%s", dc ? renc : res); free(res); } else { res = cbmimeencode(buf, code ? code : DEFCODE, !qp); printf("%s", res); free(res); } if(line) putchar('\n'); free(buf); return 0; } /* parse arguments of csv command */ int runcsv(int argc, char **argv){ CBLIST *rows, *cells; int i, j, k, dec, tb, line, html; const char *row, *cell; char *expr, *file, *buf, *res; dec = FALSE; tb = FALSE; line = FALSE; html = FALSE; expr = NULL; file = NULL; for(i = 2; i < argc; i++){ if(!file && argv[i][0] == '-'){ if(!strcmp(argv[i], "-d")){ dec = TRUE; } else if(!strcmp(argv[i], "-t")){ tb = TRUE; } else if(!strcmp(argv[i], "-l")){ line = TRUE; } else if(!strcmp(argv[i], "-e")){ if(++i >= argc) usage(); expr = argv[i]; } else if(!strcmp(argv[i], "-html")){ html = TRUE; } else { usage(); } } else if(!file){ file = argv[i]; } else { usage(); } } buf = NULL; if(expr){ buf = cbmemdup(expr, -1); } else if(file){ if(!(buf = cbreadfile(file, NULL))){ fprintf(stderr, "%s: %s: cannot open\n", progname, file); return 1; } } else { buf = readstdin(NULL); } if(tb || html){ if(html) printf("\n"); rows = cbcsvrows(buf); for(i = 0; i < cblistnum(rows); i++){ if(html) printf(""); row = cblistval(rows, i, NULL); cells = cbcsvcells(row); for(j = 0; j < cblistnum(cells); j++){ cell = cblistval(cells, j, NULL); if(html){ printf(""); } else { if(j > 0) putchar('\t'); for(k = 0; cell[k] != '\0'; k++){ if(((unsigned char *)cell)[k] >= 0x20) putchar(cell[k]); } } } cblistclose(cells); if(html) printf(""); putchar('\n'); } cblistclose(rows); if(html) printf("
"); for(k = 0; cell[k] != '\0'; k++){ if(cell[k] == '\r' || cell[k] == '\n'){ printf("
"); if(cell[k] == '\r' && cell[k] == '\n') k++; } else { switch(cell[k]){ case '&': printf("&"); break; case '<': printf("<"); break; case '>': printf(">"); break; default: putchar(cell[k]); break; } } } printf("
\n"); } else if(dec){ res = cbcsvunescape(buf); for(i = 0; res[i] != '\0'; i++){ putchar(res[i]); } free(res); } else { res = cbcsvescape(buf); for(i = 0; res[i] != '\0'; i++){ putchar(res[i]); } free(res); } if(line) putchar('\n'); free(buf); return 0; } /* parse arguments of xml command */ int runxml(int argc, char **argv){ CBLIST *elems; CBMAP *attrs; int i, j, dec, pb, line, tsv, div; const char *elem, *attr; char *expr, *file, *buf, *res; dec = FALSE; pb = FALSE; line = FALSE; tsv = FALSE; expr = NULL; file = NULL; for(i = 2; i < argc; i++){ if(!file && argv[i][0] == '-'){ if(!strcmp(argv[i], "-d")){ dec = TRUE; } else if(!strcmp(argv[i], "-p")){ pb = TRUE; } else if(!strcmp(argv[i], "-l")){ line = TRUE; } else if(!strcmp(argv[i], "-e")){ if(++i >= argc) usage(); expr = argv[i]; } else if(!strcmp(argv[i], "-tsv")){ tsv = TRUE; } else { usage(); } } else if(!file){ file = argv[i]; } else { usage(); } } buf = NULL; if(expr){ buf = cbmemdup(expr, -1); } else if(file){ if(!(buf = cbreadfile(file, NULL))){ fprintf(stderr, "%s: %s: cannot open\n", progname, file); return 1; } } else { buf = readstdin(NULL); } if(pb || tsv){ elems = cbxmlbreak(buf, FALSE); for(i = 0; i < cblistnum(elems); i++){ elem = cblistval(elems, i, NULL); div = FALSE; if(elem[0] == '<'){ if(cbstrfwimatch(elem, "")){ printf("EMPTAG"); div = TRUE; } else { printf("BEGTAG"); div = TRUE; } } else { printf("TEXT"); } putchar('\t'); if(tsv){ if(div){ attrs = cbxmlattrs(elem); cbmapiterinit(attrs); for(j = 0; (attr = cbmapiternext(attrs, NULL)) != NULL; j++){ if(j < 1){ printf("%s", cbmapget(attrs, attr, -1, NULL)); } else { printf("\t%s\t%s", attr, cbmapget(attrs, attr, -1, NULL)); } } cbmapclose(attrs); } else { res = cbxmlunescape(elem); for(j = 0; elem[j] != '\0'; j++){ if(((unsigned char *)elem)[j] < 0x20 || elem[j] == '%'){ printf("%%%02X", elem[j]); } else { putchar(elem[j]); } } free(res); } } else { printf("%s", elem); } putchar('\n'); } cblistclose(elems); } else if(dec){ res = cbxmlunescape(buf); for(i = 0; res[i] != '\0'; i++){ putchar(res[i]); } free(res); } else { res = cbxmlescape(buf); for(i = 0; res[i] != '\0'; i++){ putchar(res[i]); } free(res); } if(line) putchar('\n'); free(buf); return 0; } /* parse arguments of zlib command */ int runzlib(int argc, char **argv){ unsigned int sum; int i, bsiz, rsiz, dec, gz, crc; char *file, *buf, *res; dec = FALSE; gz = FALSE; crc = FALSE; file = NULL; for(i = 2; i < argc; i++){ if(!file && argv[i][0] == '-'){ if(!strcmp(argv[i], "-d")){ dec = TRUE; } else if(!strcmp(argv[i], "-gz")){ gz = TRUE; } else if(!strcmp(argv[i], "-crc")){ crc = TRUE; } else { usage(); } } else if(!file){ file = argv[i]; } else { usage(); } } buf = NULL; if(file){ if(!(buf = cbreadfile(file, &bsiz))){ fprintf(stderr, "%s: %s: cannot open\n", progname, file); return 1; } } else { buf = readstdin(&bsiz); } if(crc){ sum = cbgetcrc(buf, bsiz); for(i = 0; i < sizeof(int); i++){ printf("%02x", sum / 0x1000000); sum <<= 8; } putchar('\n'); } else if(dec){ if(!(res = gz ? cbgzdecode(buf, bsiz, &rsiz) : cbinflate(buf, bsiz, &rsiz))){ fprintf(stderr, "%s: inflate failed\n", progname); free(buf); return 1; } for(i = 0; i < rsiz; i++){ putchar(res[i]); } free(res); } else { if(!(res = gz ? cbgzencode(buf, bsiz, &rsiz) : cbdeflate(buf, bsiz, &rsiz))){ fprintf(stderr, "%s: deflate failed\n", progname); free(buf); return 1; } for(i = 0; i < rsiz; i++){ putchar(res[i]); } free(res); } free(buf); return 0; } /* parse arguments of lzo command */ int runlzo(int argc, char **argv){ int i, bsiz, rsiz, dec; char *file, *buf, *res; dec = FALSE; file = NULL; for(i = 2; i < argc; i++){ if(!file && argv[i][0] == '-'){ if(!strcmp(argv[i], "-d")){ dec = TRUE; } else { usage(); } } else if(!file){ file = argv[i]; } else { usage(); } } buf = NULL; if(file){ if(!(buf = cbreadfile(file, &bsiz))){ fprintf(stderr, "%s: %s: cannot open\n", progname, file); return 1; } } else { buf = readstdin(&bsiz); } if(dec){ if(!(res = cblzodecode(buf, bsiz, &rsiz))){ fprintf(stderr, "%s: decode failed\n", progname); free(buf); return 1; } for(i = 0; i < rsiz; i++){ putchar(res[i]); } free(res); } else { if(!(res = cblzoencode(buf, bsiz, &rsiz))){ fprintf(stderr, "%s: encode failed\n", progname); free(buf); return 1; } for(i = 0; i < rsiz; i++){ putchar(res[i]); } free(res); } free(buf); return 0; } /* parse arguments of bzip command */ int runbzip(int argc, char **argv){ int i, bsiz, rsiz, dec; char *file, *buf, *res; dec = FALSE; file = NULL; for(i = 2; i < argc; i++){ if(!file && argv[i][0] == '-'){ if(!strcmp(argv[i], "-d")){ dec = TRUE; } else { usage(); } } else if(!file){ file = argv[i]; } else { usage(); } } buf = NULL; if(file){ if(!(buf = cbreadfile(file, &bsiz))){ fprintf(stderr, "%s: %s: cannot open\n", progname, file); return 1; } } else { buf = readstdin(&bsiz); } if(dec){ if(!(res = cbbzdecode(buf, bsiz, &rsiz))){ fprintf(stderr, "%s: decode failed\n", progname); free(buf); return 1; } for(i = 0; i < rsiz; i++){ putchar(res[i]); } free(res); } else { if(!(res = cbbzencode(buf, bsiz, &rsiz))){ fprintf(stderr, "%s: encode failed\n", progname); free(buf); return 1; } for(i = 0; i < rsiz; i++){ putchar(res[i]); } free(res); } free(buf); return 0; } /* parse arguments of iconv command */ int runiconv(int argc, char **argv){ CBDATUM *datum; const char *rcode; char *icode, *ocode, *ltype, *file, *buf, *res, *norm, *orig; int i, cn, wc, bsiz, rsiz, nsiz, osiz, miss; icode = NULL; ocode = NULL; ltype = NULL; file = NULL; cn = FALSE; wc = FALSE; for(i = 2; i < argc; i++){ if(!file && argv[i][0] == '-'){ if(!strcmp(argv[i], "-ic")){ if(++i >= argc) usage(); icode = argv[i]; } else if(!strcmp(argv[i], "-oc")){ if(++i >= argc) usage(); ocode = argv[i]; } else if(!strcmp(argv[i], "-ol")){ if(++i >= argc) usage(); ltype = argv[i]; } else if(!strcmp(argv[i], "-cn")){ cn = TRUE; } else if(!strcmp(argv[i], "-wc")){ wc = TRUE; } else if(!strcmp(argv[i], "-um")){ shouucsmap(); } else { usage(); } } else if(!file){ file = argv[i]; } else { usage(); } } buf = NULL; if(file){ if(!(buf = cbreadfile(file, &bsiz))){ fprintf(stderr, "%s: %s: cannot open\n", progname, file); return 1; } } else { buf = readstdin(&bsiz); } miss = 0; if(cn){ printf("%s\n", cbencname(buf, bsiz)); } else if(wc){ printf("%d\n", cbstrcountutf(buf)); } else { rcode = icode ? icode : cbencname(buf, bsiz); if(!(res = cbiconv(buf, bsiz, rcode, ocode ? ocode : DEFCODE, &rsiz, &miss))){ fprintf(stderr, "%s: iconv failed\n", progname); free(buf); return 1; } if(miss > 0) fprintf(stderr, "%s: missing %d characters\n", progname, miss); if(ltype && (!cbstricmp(ltype, "u") || !cbstricmp(ltype, "unix") || !cbstricmp(ltype, "lf"))){ ltype = "\n"; } else if(ltype && (!cbstricmp(ltype, "d") || !cbstricmp(ltype, "dos") || !cbstricmp(ltype, "crlf"))){ ltype = "\r\n"; } else if(ltype && (!cbstricmp(ltype, "m") || !cbstricmp(ltype, "mac") || !cbstricmp(ltype, "cr"))){ ltype = "\r"; } else { ltype = NULL; } if(ltype){ if(!(norm = cbiconv(res, rsiz, ocode, "UTF-8", &nsiz, NULL))){ fprintf(stderr, "%s: iconv failed\n", progname); free(res); free(buf); return 1; } datum = cbdatumopen(NULL, -1); for(i = 0; i < nsiz; i++){ if(norm[i] == '\r'){ if(norm[i+1] == '\n') i++; cbdatumcat(datum, ltype, -1); } else if(norm[i] == '\n'){ cbdatumcat(datum, ltype, -1); } else { cbdatumcat(datum, norm + i, 1); } } if(!(orig = cbiconv(cbdatumptr(datum), cbdatumsize(datum), "UTF-8", ocode, &osiz, NULL))){ fprintf(stderr, "%s: iconv failed\n", progname); cbdatumclose(datum); free(norm); free(res); free(buf); return 1; } for(i = 0; i < osiz; i++){ putchar(orig[i]); } free(orig); cbdatumclose(datum); free(norm); } else { for(i = 0; i < rsiz; i++){ putchar(res[i]); } } free(res); } free(buf); return miss > 0 ? 1 : 0; } /* parse arguments of date command */ int rundate(int argc, char **argv){ int i, wb, rb, utc, jl; char *date, *res; time_t t; wb = FALSE; rb = FALSE; utc = FALSE; date = NULL; for(i = 2; i < argc; i++){ if(!date && argv[i][0] == '-'){ if(!strcmp(argv[i], "-wf")){ wb = TRUE; } else if(!strcmp(argv[i], "-rf")){ rb = TRUE; } else if(!strcmp(argv[i], "-utc")){ utc = TRUE; } else { usage(); } } else if(!date){ date = argv[i]; } else { usage(); } } jl = utc ? 0 : cbjetlag(); if(date){ t = cbstrmktime(date); } else { t = time(NULL); } if(wb){ res = cbdatestrwww(t, jl); } else if(rb){ res = cbdatestrhttp(t, jl); } else { res = cbsprintf("%d", (int)t); } if(t >= 0){ printf("%s\n", res); } else { if(date){ fprintf(stderr, "%s: %s: invalid date format\n", progname, date); } else { fprintf(stderr, "%s: invalid time setting\n", progname); } } free(res); return 0; } /* show mapping of UCS-2 and exit. */ void shouucsmap(void){ unsigned char buf[2], *tmp; int i, j, tsiz; for(i = 0; i < 65536; i++){ buf[0] = i / 256; buf[1] = i % 256; printf("%d\t", i); printf("U+%02X%02X\t", buf[0], buf[1]); printf("\"\\x%x\\x%x\"\t", buf[0], buf[1]); if((tmp = (unsigned char *)cbiconv((char *)buf, 2, "UTF-16BE", "UTF-8", &tsiz, NULL)) != NULL){ if(tsiz > 0){ printf("\""); for(j = 0; j < tsiz; j++){ printf("\\x%x", tmp[j]); } printf("\""); } else { printf("NULL"); } free(tmp); } printf("\n"); } exit(0); } /* END OF FILE */ qdbm-1.8.78/hovel.c0000644000175000017500000003704210610627747013045 0ustar mikiomikio/************************************************************************************************* * Implementation of Hovel * Copyright (C) 2000-2007 Mikio Hirabayashi * This file is part of QDBM, Quick Database Manager. * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU * Lesser General Public License as published by the Free Software Foundation; either version * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * You should have received a copy of the GNU Lesser General Public License along with QDBM; if * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. *************************************************************************************************/ #define QDBM_INTERNAL 1 #include "hovel.h" #include "myconf.h" #define HV_INITBNUM 32749 /* initial bucket number */ #define HV_ALIGNSIZ 16 /* size of alignment */ /* private function prototypes */ static int gdbm_geterrno(int ecode); /************************************************************************************************* * public objects *************************************************************************************************/ /* String containing the version information. */ char *gdbm_version = "Powered by QDBM"; /* Get a message string corresponding to an error code. */ char *gdbm_strerror(gdbm_error gdbmerrno){ switch(gdbmerrno){ case GDBM_NO_ERROR: return "No error"; case GDBM_MALLOC_ERROR: return "Malloc error"; case GDBM_BLOCK_SIZE_ERROR: return "Block size error"; case GDBM_FILE_OPEN_ERROR: return "File open error"; case GDBM_FILE_WRITE_ERROR: return "File write error"; case GDBM_FILE_SEEK_ERROR: return "File seek error"; case GDBM_FILE_READ_ERROR: return "File read error"; case GDBM_BAD_MAGIC_NUMBER: return "Bad magic number"; case GDBM_EMPTY_DATABASE: return "Empty database"; case GDBM_CANT_BE_READER: return "Can't be reader"; case GDBM_CANT_BE_WRITER: return "Can't be writer"; case GDBM_READER_CANT_DELETE: return "Reader can't delete"; case GDBM_READER_CANT_STORE: return "Reader can't store"; case GDBM_READER_CANT_REORGANIZE: return "Reader can't reorganize"; case GDBM_UNKNOWN_UPDATE: return "Unknown update"; case GDBM_ITEM_NOT_FOUND: return "Item not found"; case GDBM_REORGANIZE_FAILED: return "Reorganize failed"; case GDBM_CANNOT_REPLACE: return "Cannot replace"; case GDBM_ILLEGAL_DATA: return "Illegal data"; case GDBM_OPT_ALREADY_SET: return "Option already set"; case GDBM_OPT_ILLEGAL: return "Illegal option"; } return "(invalid ecode)"; } /* Get a database handle after the fashion of GDBM. */ GDBM_FILE gdbm_open(char *name, int block_size, int read_write, int mode, void (*fatal_func)(void)){ GDBM_FILE dbf; int dpomode; DEPOT *depot; int flags, fd; assert(name); dpomode = DP_OREADER; flags = O_RDONLY; if(read_write & GDBM_READER){ dpomode = GDBM_READER; if(read_write & GDBM_NOLOCK) dpomode |= DP_ONOLCK; if(read_write & GDBM_LOCKNB) dpomode |= DP_OLCKNB; flags = O_RDONLY; } else if(read_write & GDBM_WRITER){ dpomode = DP_OWRITER; if(read_write & GDBM_NOLOCK) dpomode |= DP_ONOLCK; if(read_write & GDBM_LOCKNB) dpomode |= DP_OLCKNB; flags = O_RDWR; } else if(read_write & GDBM_WRCREAT){ dpomode = DP_OWRITER | DP_OCREAT; if(read_write & GDBM_NOLOCK) dpomode |= DP_ONOLCK; if(read_write & GDBM_LOCKNB) dpomode |= DP_OLCKNB; if(read_write & GDBM_SPARSE) dpomode |= DP_OSPARSE; flags = O_RDWR | O_CREAT; } else if(read_write & GDBM_NEWDB){ dpomode = DP_OWRITER | DP_OCREAT | DP_OTRUNC; if(read_write & GDBM_NOLOCK) dpomode |= DP_ONOLCK; if(read_write & GDBM_LOCKNB) dpomode |= DP_OLCKNB; if(read_write & GDBM_SPARSE) dpomode |= DP_OSPARSE; flags = O_RDWR | O_CREAT | O_TRUNC; } else { gdbm_errno = GDBM_ILLEGAL_DATA; return NULL; } mode |= 00600; if((fd = open(name, flags, mode)) == -1 || close(fd) == -1){ gdbm_errno = GDBM_FILE_OPEN_ERROR; return NULL; } if(!(depot = dpopen(name, dpomode, HV_INITBNUM))){ gdbm_errno = gdbm_geterrno(dpecode); if(dpecode == DP_ESTAT) gdbm_errno = GDBM_FILE_OPEN_ERROR; return NULL; } if(dpomode & DP_OWRITER){ if(!dpsetalign(depot, HV_ALIGNSIZ)){ gdbm_errno = gdbm_geterrno(dpecode); dpclose(depot); } } if((dpomode & DP_OWRITER) && (read_write & GDBM_SYNC)){ if(!dpsync(depot)){ gdbm_errno = gdbm_geterrno(dpecode); dpclose(depot); } } if(!(dbf = malloc(sizeof(GDBM)))){ gdbm_errno = GDBM_MALLOC_ERROR; dpclose(depot); return NULL; } dbf->depot = depot; dbf->curia = NULL; dbf->syncmode = (dpomode & DP_OWRITER) && (read_write & GDBM_SYNC) ? TRUE : FALSE; return dbf; } /* Get a database handle after the fashion of QDBM. */ GDBM_FILE gdbm_open2(char *name, int read_write, int mode, int bnum, int dnum, int align){ GDBM_FILE dbf; int dpomode, cromode, flags, fd; struct stat sbuf; DEPOT *depot; CURIA *curia; assert(name); dpomode = DP_OREADER; cromode = CR_OREADER; flags = O_RDONLY; if(read_write & GDBM_READER){ dpomode = DP_OREADER; cromode = CR_OREADER; if(read_write & GDBM_NOLOCK){ dpomode |= DP_ONOLCK; cromode |= CR_ONOLCK; } if(read_write & GDBM_LOCKNB){ dpomode |= DP_OLCKNB; cromode |= CR_OLCKNB; } flags = O_RDONLY; } else if(read_write & GDBM_WRITER){ dpomode = DP_OWRITER; cromode = CR_OWRITER; if(read_write & GDBM_NOLOCK){ dpomode |= DP_ONOLCK; cromode |= CR_ONOLCK; } if(read_write & GDBM_LOCKNB){ dpomode |= DP_OLCKNB; cromode |= CR_OLCKNB; } flags = O_RDWR; } else if(read_write & GDBM_WRCREAT){ dpomode = DP_OWRITER | DP_OCREAT; cromode = CR_OWRITER | CR_OCREAT; if(read_write & GDBM_NOLOCK){ dpomode |= DP_ONOLCK; cromode |= CR_ONOLCK; } if(read_write & GDBM_LOCKNB){ dpomode |= DP_OLCKNB; cromode |= CR_OLCKNB; } if(read_write & GDBM_SPARSE){ dpomode |= DP_OSPARSE; cromode |= CR_OSPARSE; } flags = O_RDWR | O_CREAT; } else if(read_write & GDBM_NEWDB){ dpomode = DP_OWRITER | DP_OCREAT | DP_OTRUNC; cromode = CR_OWRITER | CR_OCREAT | CR_OTRUNC; if(read_write & GDBM_NOLOCK){ dpomode |= DP_ONOLCK; cromode |= CR_ONOLCK; } if(read_write & GDBM_LOCKNB){ dpomode |= DP_OLCKNB; cromode |= CR_OLCKNB; } if(read_write & GDBM_SPARSE){ dpomode |= DP_OSPARSE; cromode |= CR_OSPARSE; } flags = O_RDWR | O_CREAT | O_TRUNC; } else { gdbm_errno = GDBM_ILLEGAL_DATA; return NULL; } if(lstat(name, &sbuf) != -1){ if(S_ISDIR(sbuf.st_mode)){ if(dnum < 1) dnum = 1; } else { dnum = 0; } } depot = NULL; curia = NULL; if(dnum > 0){ mode |= 00700; if((cromode & CR_OCREAT)){ if(mkdir(name, mode) == -1 && errno != EEXIST){ gdbm_errno = GDBM_FILE_OPEN_ERROR; return NULL; } } if(!(curia = cropen(name, cromode, bnum, dnum))){ gdbm_errno = gdbm_geterrno(dpecode); return NULL; } if(cromode & CR_OWRITER) crsetalign(curia, align); if((cromode & CR_OWRITER) && (read_write & GDBM_SYNC)) crsync(curia); } else { mode |= 00600; if(dpomode & DP_OWRITER){ if((fd = open(name, flags, mode)) == -1 || close(fd) == -1){ gdbm_errno = GDBM_FILE_OPEN_ERROR; return NULL; } } if(!(depot = dpopen(name, dpomode, bnum))){ gdbm_errno = gdbm_geterrno(dpecode); return NULL; } if(dpomode & DP_OWRITER) dpsetalign(depot, align); if((dpomode & DP_OWRITER) && (read_write & GDBM_SYNC)) dpsync(depot); } if(!(dbf = malloc(sizeof(GDBM)))){ gdbm_errno = GDBM_MALLOC_ERROR; if(depot) dpclose(depot); if(curia) crclose(curia); return NULL; } dbf->depot = depot; dbf->curia = curia; dbf->syncmode = (dpomode & DP_OWRITER) && (read_write & GDBM_SYNC) ? TRUE : FALSE; return dbf; } /* Close a database handle. */ void gdbm_close(GDBM_FILE dbf){ assert(dbf); if(dbf->depot){ if(dbf->syncmode) dpsync(dbf->depot); dpclose(dbf->depot); } else { if(dbf->syncmode) crsync(dbf->curia); crclose(dbf->curia); } free(dbf); } /* Store a record. */ int gdbm_store(GDBM_FILE dbf, datum key, datum content, int flag){ int dmode; assert(dbf); if(!key.dptr || key.dsize < 0 || !content.dptr || content.dsize < 0){ gdbm_errno = GDBM_ILLEGAL_DATA; return -1; } if(dbf->depot){ if(!dpwritable(dbf->depot)){ gdbm_errno = GDBM_READER_CANT_STORE; return -1; } dmode = (flag == GDBM_INSERT) ? DP_DKEEP : DP_DOVER; if(!dpput(dbf->depot, key.dptr, key.dsize, content.dptr, content.dsize, dmode)){ gdbm_errno = gdbm_geterrno(dpecode); if(dpecode == DP_EKEEP) return 1; return -1; } if(dbf->syncmode && !dpsync(dbf->depot)){ gdbm_errno = gdbm_geterrno(dpecode); return -1; } } else { if(!crwritable(dbf->curia)){ gdbm_errno = GDBM_READER_CANT_STORE; return -1; } dmode = (flag == GDBM_INSERT) ? CR_DKEEP : CR_DOVER; if(!crput(dbf->curia, key.dptr, key.dsize, content.dptr, content.dsize, dmode)){ gdbm_errno = gdbm_geterrno(dpecode); if(dpecode == DP_EKEEP) return 1; return -1; } if(dbf->syncmode && !crsync(dbf->curia)){ gdbm_errno = gdbm_geterrno(dpecode); return -1; } } return 0; } /* Delete a record. */ int gdbm_delete(GDBM_FILE dbf, datum key){ assert(dbf); if(!key.dptr || key.dsize < 0){ gdbm_errno = GDBM_ILLEGAL_DATA; return -1; } if(dbf->depot){ if(!dpwritable(dbf->depot)){ gdbm_errno = GDBM_READER_CANT_DELETE; return -1; } if(!dpout(dbf->depot, key.dptr, key.dsize)){ gdbm_errno = gdbm_geterrno(dpecode); return -1; } if(dbf->syncmode && !dpsync(dbf->depot)){ gdbm_errno = gdbm_geterrno(dpecode); return -1; } } else { if(!crwritable(dbf->curia)){ gdbm_errno = GDBM_READER_CANT_DELETE; return -1; } if(!crout(dbf->curia, key.dptr, key.dsize)){ gdbm_errno = gdbm_geterrno(dpecode); return -1; } if(dbf->syncmode && !crsync(dbf->curia)){ gdbm_errno = gdbm_geterrno(dpecode); return -1; } } return 0; } /* Retrieve a record. */ datum gdbm_fetch(GDBM_FILE dbf, datum key){ datum content; char *vbuf; int vsiz; assert(dbf); if(!key.dptr || key.dsize < 0){ gdbm_errno = GDBM_ILLEGAL_DATA; content.dptr = NULL; content.dsize = 0; return content; } if(dbf->depot){ if(!(vbuf = dpget(dbf->depot, key.dptr, key.dsize, 0, -1, &vsiz))){ gdbm_errno = gdbm_geterrno(dpecode); content.dptr = NULL; content.dsize = 0; return content; } } else { if(!(vbuf = crget(dbf->curia, key.dptr, key.dsize, 0, -1, &vsiz))){ gdbm_errno = gdbm_geterrno(dpecode); content.dptr = NULL; content.dsize = 0; return content; } } content.dptr = vbuf; content.dsize = vsiz; return content; } /* Check whether a record exists or not. */ int gdbm_exists(GDBM_FILE dbf, datum key){ assert(dbf); if(!key.dptr || key.dsize < 0){ gdbm_errno = GDBM_ILLEGAL_DATA; return FALSE; } if(dbf->depot){ if(dpvsiz(dbf->depot, key.dptr, key.dsize) == -1){ gdbm_errno = gdbm_geterrno(dpecode); return FALSE; } } else { if(crvsiz(dbf->curia, key.dptr, key.dsize) == -1){ gdbm_errno = gdbm_geterrno(dpecode); return FALSE; } } return TRUE; } /* Get the first key of a database. */ datum gdbm_firstkey(GDBM_FILE dbf){ datum key; assert(dbf); memset(&key, 0, sizeof(datum)); if(dbf->depot){ if(dprnum(dbf->depot) < 1){ gdbm_errno = GDBM_EMPTY_DATABASE; key.dptr = NULL; key.dsize = 0; return key; } dpiterinit(dbf->depot); return gdbm_nextkey(dbf, key); } else { if(crrnum(dbf->curia) < 1){ gdbm_errno = GDBM_EMPTY_DATABASE; key.dptr = NULL; key.dsize = 0; return key; } criterinit(dbf->curia); return gdbm_nextkey(dbf, key); } } /* Get the next key of a database. */ datum gdbm_nextkey(GDBM_FILE dbf, datum key){ char *kbuf; int ksiz; assert(dbf); if(dbf->depot){ if(!(kbuf = dpiternext(dbf->depot, &ksiz))){ gdbm_errno = gdbm_geterrno(dpecode); key.dptr = NULL; key.dsize = 0; return key; } } else { if(!(kbuf = criternext(dbf->curia, &ksiz))){ gdbm_errno = gdbm_geterrno(dpecode); key.dptr = NULL; key.dsize = 0; return key; } } key.dptr = kbuf; key.dsize = ksiz; return key; } /* Synchronize contents of updating with the file and the device. */ void gdbm_sync(GDBM_FILE dbf){ assert(dbf); if(dbf->depot){ if(!dpsync(dbf->depot)) gdbm_errno = gdbm_geterrno(dpecode); } else { if(!crsync(dbf->curia)) gdbm_errno = gdbm_geterrno(dpecode); } } /* Reorganize a database. */ int gdbm_reorganize(GDBM_FILE dbf){ assert(dbf); if(dbf->depot){ if(!dpwritable(dbf->depot)){ gdbm_errno = GDBM_READER_CANT_REORGANIZE; return -1; } if(!dpoptimize(dbf->depot, dprnum(dbf->depot) >= HV_INITBNUM ? -1 : HV_INITBNUM)){ gdbm_errno = gdbm_geterrno(dpecode); return -1; } } else { if(!crwritable(dbf->curia)){ gdbm_errno = GDBM_READER_CANT_REORGANIZE; return -1; } if(!croptimize(dbf->curia, crrnum(dbf->curia) >= HV_INITBNUM ? -1 : HV_INITBNUM)){ gdbm_errno = gdbm_geterrno(dpecode); return -1; } } return 0; } /* Get the file descriptor of a database file. */ int gdbm_fdesc(GDBM_FILE dbf){ assert(dbf); if(dbf->depot){ return dpfdesc(dbf->depot); } else { return -1; } } /* No effect. */ int gdbm_setopt(GDBM_FILE dbf, int option, int *value, int size){ assert(dbf); return 0; } /************************************************************************************************* * features for experts *************************************************************************************************/ /* Get the pointer of the last happened error code. */ int *gdbm_errnoptr(void){ static int deferrno = GDBM_NO_ERROR; void *ptr; if(_qdbm_ptsafe){ if(!(ptr = _qdbm_settsd(&deferrno, sizeof(int), &deferrno))){ deferrno = GDBM_ILLEGAL_DATA; return &deferrno; } return (int *)ptr; } return &deferrno; } /************************************************************************************************* * private objects *************************************************************************************************/ /* Get the error code of GDBM corresponding to an error code of Depot. `ecode' specifies an error code of Depot. The return value is the error code of GDBM. */ static int gdbm_geterrno(int ecode){ switch(ecode){ case DP_ENOERR: return GDBM_NO_ERROR; case DP_EBROKEN: return GDBM_BAD_MAGIC_NUMBER; case DP_EKEEP: return GDBM_CANNOT_REPLACE; case DP_ENOITEM: return GDBM_ITEM_NOT_FOUND; case DP_EALLOC: return GDBM_MALLOC_ERROR; case DP_EOPEN: return GDBM_FILE_OPEN_ERROR; case DP_ESEEK: return GDBM_FILE_SEEK_ERROR; case DP_EREAD: return GDBM_FILE_READ_ERROR; case DP_EWRITE: return GDBM_FILE_WRITE_ERROR; case DP_EMKDIR: return GDBM_FILE_OPEN_ERROR; default: break; } return GDBM_ILLEGAL_DATA; } /* END OF FILE */ qdbm-1.8.78/ChangeLog0000644000175000017500000006136311426313751013332 0ustar mikiomikio2007-12-22 Mikio Hirabayashi - Converters from Depot/Curia/Villa to TCHDB/TCBDB were added. - Release: 1.8.78 2007-10-18 Mikio Hirabayashi - code clean-up. - Release: 1.8.77 2007-03-07 Mikio Hirabayashi - The hash function of on-memory map was optimized. - A bug related to large object was fixed. - Release: 1.8.76 2006-11-10 Mikio Hirabayashi - The utility API was enhanced. - A bug related to B+ tree API for Ruby was fixed. - Release: 1.8.75 2006-11-02 Mikio Hirabayashi - A bug related to optimization on Intel Mac series was escaped. - Release: 1.8.74 2006-10-20 Mikio Hirabayashi - A bug related to BZIP2 encoding was fixed. - Release: 1.8.73 2006-10-06 Mikio Hirabayashi - The utility API was enhanced. - Release: 1.8.72 2006-08-24 Mikio Hirabayashi - Makefile was modified to assure portability. - Silent flag was added to the C++ API, the Java API, and the Ruby API. - Release: 1.8.71 2006-08-18 Mikio Hirabayashi - A bug of segmentation fault on BSD was fixed. - A test command for checking multi thread safety was added. - Release: 1.8.70 2006-08-15 Mikio Hirabayashi - Mutex controll in C++ API became refined. - Release: 1.8.69 2006-08-08 Mikio Hirabayashi - A bug about memory alignment was fixed. - A bug of handling meta data on big endian platforms was fixed. - Release: 1.8.68 2006-08-05 Mikio Hirabayashi - A bug about memory alignment was fixed. - A bug about parsing MIME was fixed. - Release: 1.8.67 2006-08-05 Mikio Hirabayashi - The utility API was enhanced. - Release: 1.8.66 2006-08-03 Mikio Hirabayashi - The extended API was enhanced. - The extended advanced API was enhanced. - Release: 1.8.65 2006-07-28 Mikio Hirabayashi - A bug of Makefile ralated to optimization was fixed. - Release: 1.8.64 2006-07-24 Mikio Hirabayashi - A lot of functions were replaced by macros. - The utility API was enhanced. - Release: 1.8.63 2006-07-20 Mikio Hirabayashi - A lot of functions were replaced by macros. - The URL resolver was to allow unescaped meta characters. - The advanced API was enhanced. - Release: 1.8.62 2006-07-14 Mikio Hirabayashi - A bug of the size checking function of the extended API was fixed. - The advanced API was enhanced. - Release: 1.8.61 2006-06-03 Mikio Hirabayashi - The basic API was enhanced. - The extended API was enhanced. - The advanced API was enhanced. - Multiple cursor class is now supported on the java API. - Release: 1.8.60 2006-05-30 Mikio Hirabayashi - The basic API was enhanced. - The extended API was enhanced. - The advanced API was enhanced. - A bug of Makefile for Mac OS X support was fixed. - Release: 1.8.59 2006-05-28 Mikio Hirabayashi - The basic API was enhanced. - The advanced API was enhanced. - Release: 1.8.58 2006-05-20 Mikio Hirabayashi - The basic API was enhanced. - The utility API was enhanced. - Release: 1.8.57 2006-05-17 Mikio Hirabayashi - A bug of URL decoder was fixed. - Release: 1.8.56 2006-05-15 Mikio Hirabayashi - The extended API was enhanced. - The utility API was enhanced. - Release: 1.8.55 2006-05-15 Mikio Hirabayashi - The basic API was enhanced. - Release: 1.8.54 2006-05-10 Mikio Hirabayashi - AIX is now supported. - The utility API was enhanced. - Release: 1.8.53 2006-05-04 Mikio Hirabayashi - A bug about evaluating RFC822 date format was fixed. - Release: 1.8.52 2006-05-02 Mikio Hirabayashi - A bug about evaluating RFC822 date format was fixed. - Warings from GCC 4.1.x were dealt with. - Missing functions in qdbm.def were supplied. - Release: 1.8.51 2006-04-28 Mikio Hirabayashi - The utility API was enhanced. - Release: 1.8.50 2006-04-19 Mikio Hirabayashi - A parameter of dynamic linking library on Mac OS X was modified. - The utility API was enhanced. - Release: 1.8.49 2006-03-27 Mikio Hirabayashi - The utility API was enhanced. - Release: 1.8.48 2006-03-10 Mikio Hirabayashi - LTmakefile was modified. - The utility API was enhanced. - Release: 1.8.47 2006-02-20 Mikio Hirabayashi - The utility API was enhanced. - Release: 1.8.46 2006-01-28 Mikio Hirabayashi - Alignment algorithm was improved. - A bug of mmap emulation on Windows was fixed. - Release: 1.8.45 2006-01-24 Mikio Hirabayashi - A bug of handling meta data on big endian platforms was fixed. - The advanced API was enhanced. - Release: 1.8.44 2006-01-24 Mikio Hirabayashi - A bug of mmap emulation on Windows was fixed. - Release: 1.8.43 2006-01-22 Mikio Hirabayashi - mmap emulation on Windows was enhanced. - Release: 1.8.42 2006-01-13 Mikio Hirabayashi - Compression of pages of B+ tree with LZO and BZIP was added. - Release: 1.8.41 2006-01-08 Mikio Hirabayashi - Configuration for VC++ was to build DLL. - Release: 1.8.40 2006-01-04 Mikio Hirabayashi - The advanced API was enhanced. - Release: 1.8.39 2006-01-01 Mikio Hirabayashi - The advanced API was enhanced. - Release: 1.8.38 2005-12-26 Mikio Hirabayashi - Functions to set the size of the free block pool were added. - Commands line tools were enhanced. - Release: 1.8.37 2005-12-24 Mikio Hirabayashi - Free block pool was enhanced. - Commands line tools were enhanced. - Release: 1.8.36 2005-11-30 Mikio Hirabayashi - The utility API was enhanced. - The extended advanced API was enhanced. - All stat calls were replaced with lstat calls. - Release: 1.8.35 2005-11-22 Mikio Hirabayashi - A bug of i-node duplication on MinGW was fixed. - Release: 1.8.34 2005-09-09 Mikio Hirabayashi - Compressing options of ZLIB was changed. - The utility API was enhanced. - Release: 1.8.33 2005-08-30 Mikio Hirabayashi - A bug of backward string matching was fixed. - The utility API was enhanced. - Release: 1.8.32 2005-06-19 Mikio Hirabayashi - A bug of the MIME parser was fixed. - A bug about database repair on Win32 was fixed. - A bug of Makefile for Mac OS X support was fixed. - The type of error codes of GDBM-compatibility API was changed. - Release: 1.8.31 2005-06-09 Mikio Hirabayashi - A Bug of APIs for C++ related to namespace was fixed. - The library of shared objects of C++ APIs was added. - The utility API was enhanced. - Release: 1.8.30 2005-06-01 Mikio Hirabayashi - A bug about file locking on Win32 was fixed. - Manuals of command line tools were added. - The utility API was enhanced. - Release: 1.8.29 2005-05-27 Mikio Hirabayashi - A compilation problem on hppa-linux was fixed. - A configuration file for pkg-config was added. - Release: 1.8.28 2005-05-18 Mikio Hirabayashi - Non-blocking lock was featured. - Release: 1.8.27 2005-05-12 Mikio Hirabayashi - The inverted API was enhanced. - The utility API was enhanced. - Release: 1.8.26 2005-05-10 Mikio Hirabayashi - The inverted API was enhanced. - The utility API was enhanced. - Release: 1.8.25 2005-04-25 Mikio Hirabayashi - The utility API was enhanced. - A bug about database repair on Win32 was fixed. - Release: 1.8.24 2005-04-01 Mikio Hirabayashi - The utility API was enhanced. - The extended advanced API was enhanced. - Release: 1.8.23 2005-03-24 Mikio Hirabayashi - The extended advanced API was enhanced. - The utility API was enhanced. - The inverted API was enhanced. - Test commands were enhanced. - Release: 1.8.22 2005-01-22 Mikio Hirabayashi - Functions to dump endian independent data was added. - Release: 1.8.21 2005-01-05 Mikio Hirabayashi - Sparse file support was added. - Release: 1.8.20 2005-01-02 Mikio Hirabayashi - The utility API was enhanced. - Building configurations were enhanced. - Release: 1.8.19 2004-11-10 Mikio Hirabayashi - The utility API was enhanced. - The extended advanced API was enhanced. - The inverted API was enhanced. - Release: 1.8.18 2004-09-20 Mikio Hirabayashi - The utility API was enhanced. - The CGI script for file upload was enhanced. - The spec file for RPM packages was enhanced. - Release: 1.8.17 2004-08-17 Mikio Hirabayashi - A bug in the extended API was fixed. - A bug about seek on Windows 9x was fixed. - The CGI script for file upload was enhanced. - Release: 1.8.16 2004-08-04 Mikio Hirabayashi - The utility API was enhanced. - A bug about mmap on Mac OS X was fixed. - A CGI script for file upload was added. - Building configurations were enhanced. - Release: 1.8.15 2004-07-19 Mikio Hirabayashi - The basic API was enhanced. - The extended API was enhanced. - The advanced API was enhanced. - The inverted API was enhanced. - Building configurations were enhanced. - Release: 1.8.14 2004-07-07 Mikio Hirabayashi - The utility API was enhanced. - The inverted API was enhanced. - Release: 1.8.13 2004-05-18 Mikio Hirabayashi - The utility API was enhanced. - The inverted API was enhanced. - Building configurations were enhanced. - Release: 1.8.12 2004-05-12 Mikio Hirabayashi - The utility API was enhanced. - Source codes were cleaned up for Visual C++. - Test commands were enhanced. - Building configurations were enhanced. - Release: 1.8.11 2004-04-23 Mikio Hirabayashi - Utility for performance test was enhanced. - It was escaped from a bug about mmap on FreeBSD and NetBSD. - Release: 1.8.10 2004-04-20 Mikio Hirabayashi - Logger for debugging is now featured. - It was escaped from a bug about mmap on OpenBSD. - Release: 1.8.9 2004-04-11 Mikio Hirabayashi - Processing speed was improved. - The basic API was enhanced. - The extended API was enhanced. - The configuration for VC++ was enhanced. - Release: 1.8.8 2004-03-25 Mikio Hirabayashi - The configuration of C++ API escaped from a bug of pthread. - Release: 1.8.7 2004-03-21 Mikio Hirabayashi - The extended API was enhanced. - Bugs in the utility API about memory management were fixed. - Release: 1.8.6 2004-03-12 Mikio Hirabayashi - A bug in the utility API for 64-bit platforms was fixed. - The utility API was enhanced. - Release: 1.8.5 2004-03-09 Mikio Hirabayashi - Runtime switching of whether to use ZLIB was featured. - The binary package for Win32 now features ZLIB and ICONV. - The utility API was enhanced. - Release: 1.8.4 2004-03-06 Mikio Hirabayashi - The utility API was enhanced. - A utility class of Java API was enhanced. - Test commands were enhanced. - Release: 1.8.3 2004-03-01 Mikio Hirabayashi - The utility API was enhanced. - Release: 1.8.2 2004-02-22 Mikio Hirabayashi - Processing speed of multi-thread support was improved. - Release: 1.8.1 2004-02-21 Mikio Hirabayashi - Switch to make API for C thread-safe was added. - Release: 1.8.0 2004-02-18 Mikio Hirabayashi - The utility API was enhanced. - Potential bugs in APIs for C++ were fixed. - Release: 1.7.34 2004-01-28 Mikio Hirabayashi - The extended API was enhanced. - The inverted API was enhanced. - Release: 1.7.33 2004-01-17 Mikio Hirabayashi - The inverted API was enhanced. - Release: 1.7.32 2004-01-16 Mikio Hirabayashi - The inverted API was enhanced. - Release: 1.7.31 2004-01-12 Mikio Hirabayashi - The inverted API was enhanced. - Release: 1.7.30 2004-01-11 Mikio Hirabayashi - The utility API was enhanced. - Release: 1.7.29 2004-01-09 Mikio Hirabayashi - A bug in the utility API was fixed. - Release: 1.7.28 2004-01-06 Mikio Hirabayashi - A bug in the advanced API was fixed. - The utility API was enhanced. - Release: 1.7.27 2004-01-04 Mikio Hirabayashi - The inverted API was enhanced. - Release: 1.7.26 2004-01-01 Mikio Hirabayashi - The inverted API was enhanced. - The utility API was enhanced. - Release: 1.7.25 2003-12-26 Mikio Hirabayashi - C++ export was supported in header files. - The utility API was enhanced. - Release: 1.7.24 2003-12-21 Mikio Hirabayashi - Repairing utility was added to the advanced API. - The basic API was enhanced. - The utility API was enhanced. - Release: 1.7.23 2003-12-16 Mikio Hirabayashi - Repairing utility was added to the extended API. - The utility API was enhanced. - Release: 1.7.22 2003-12-14 Mikio Hirabayashi - A utility to repair a broken database file was added. - A ulitity command for full-text search was enhanced. - Release: 1.7.21 2003-12-10 Mikio Hirabayashi - Character encoding converter was added. - Release: 1.7.20 2003-12-10 Mikio Hirabayashi - Format converter for older versions than 1.7.13 was added. - Tuning paramters of the inverted API were modified. - A CGI script for full-text search was enhanced. - Release: 1.7.19 2003-12-08 Mikio Hirabayashi - The utility API was enhanced. - The GDBM-compatible API was enhanced. - Release: 1.7.18 2003-12-05 Mikio Hirabayashi - The utility API was enhanced. - A CGI script for full-text search was enhanced. - Release: 1.7.17 2003-12-01 Mikio Hirabayashi - A CGI script for full-text search was enhanced. - A ulitity command for full-text search was enhanced. - Building configuration files were modified. - Release: 1.7.16 2003-11-30 Mikio Hirabayashi - A CGI script for full-text search was enhanced. - A ulitity command for full-text search was enhanced. - Release: 1.7.15 2003-11-29 Mikio Hirabayashi - The inverted API was enhanced. - A ulitity command for full-text search was enhanced. - A CGI script for full-text search was enhanced. - Release: 1.7.14 2003-11-27 Mikio Hirabayashi - Format of headers of database was modified. - Supporting endian conversion was abolished. - Import/export features were added to utility commands. - A ulitity command for full-text search was enhanced. - A CGI script for full-text search was enhanced. - Release: 1.7.13 2003-11-25 Mikio Hirabayashi - The utility API was enhanced. - The inverted API was enhanced. - A ulitity command for full-text search was enhanced. - A CGI script for full-text search was enhanced. - Release: 1.7.12 2003-11-23 Mikio Hirabayashi - The inverted API was enhanced. - A ulitity command for full-text search was enhanced. - A CGI script for full-text search was enhanced. - A utility class of Java API was enhanced. - Release: 1.7.11 2003-11-20 Mikio Hirabayashi - A utility class of Java API was enhanced. - Building configuration for CGI scripts was modified. - Release: 1.7.10 2003-11-20 Mikio Hirabayashi - Tuning paramters of the inverted API were modified. - A ulitity command for full-text search was enhanced. - Release: 1.7.9 2003-11-16 Mikio Hirabayashi - Optional features of compressing with ZLIB were added. - Release: 1.7.8 2003-11-05 Mikio Hirabayashi - The extended advanced API, Vista was added. - Release: 1.7.7 2003-11-03 Mikio Hirabayashi - C API compilation using Visual C++ was supported. - Odeum and its commands were enhanced. - Release: 1.7.6 2003-10-25 Mikio Hirabayashi - A ulitity command for full-text search was enhanced. - A CGI script for full-text search was enhanced. - Release: 1.7.5 2003-10-23 Mikio Hirabayashi - A CGI script for full-text search was added. - A bug of BSD support in Makefile was fixed. - Release: 1.7.4 2003-10-19 Mikio Hirabayashi - Processing speed of the inverted API was improved. - A ulitity command for full-text search was enhanced. - Release: 1.7.3 2003-10-17 Mikio Hirabayashi - The license was changed to LGPL. - An indexing command for the inverted API was added. - Release: 1.7.2 2003-10-14 Mikio Hirabayashi - A test command for the inverted API was added. - A bug about optimization in the inverted API was fixed. - Tuning paramters of the inverted API were modified. - Release: 1.7.1 2003-10-13 Mikio Hirabayashi - The inverted API, Odeum was added. - Comments in source codes increased. - Release: 1.7.0 2003-10-05 Mikio Hirabayashi - Executable commands were modified for RISC OS. - Release: 1.6.22 2003-10-05 Mikio Hirabayashi - Executable commands were modified for RISC OS. - Release: 1.6.21 2003-09-30 Mikio Hirabayashi - Naming file in RISC OS style was supported. - Hash functions were enhanced. - Release: 1.6.20 2003-09-26 Mikio Hirabayashi - The utility API was enhanced. - Test commands were added. - Release: 1.6.19 2003-09-22 Mikio Hirabayashi - Makefile for RISC OS was added. - C++ API was enhanced. - Release: 1.6.18 2003-09-14 Mikio Hirabayashi - Test commands were enhanced. - Source codes and Makefile were modified for RISC OS. - The CGI script was enhanced. - Release: 1.6.17 2003-09-13 Mikio Hirabayashi - The CGI script for administration was added. - C++ API was enhanced. - Release: 1.6.16 2003-08-28 Mikio Hirabayashi - The utility API was enhanced. - Release: 1.6.15 2003-08-16 Mikio Hirabayashi - The utility API was enhanced. - Release: 1.6.14 2003-08-11 Mikio Hirabayashi - The utility API was enhanced. - Release: 1.6.13 2003-08-05 Mikio Hirabayashi - A bug in the utility API was fixed. - Test commands were enhanced. - Release: 1.6.12 2003-07-31 Mikio Hirabayashi - C and Java APIs support compilation using MinGW. - Release: 1.6.11 2003-07-27 Mikio Hirabayashi - Perl and Ruby APIs support transaction. - Release: 1.6.10 2003-07-26 Mikio Hirabayashi - Speed of transaction was improved. - Release: 1.6.9 2003-07-24 Mikio Hirabayashi - C++ and Java APIs of B+ tree support transaction. - Release: 1.6.8 2003-07-21 Mikio Hirabayashi - C API of B+ tree supports transaction. - Bugs about Mutex in C++ and Java APIs were fixed. - Release: 1.6.7 2003-07-18 Mikio Hirabayashi - C++ and Java APIs of database abstraction were simplified. - Ruby API of B+ tree was simplified. - Release: 1.6.6 2003-07-16 Mikio Hirabayashi - Ruby API of B+ tree was added. - C, C++, Java and Perl APIs of B+ tree were enhanced. - Release: 1.6.5 2003-07-13 Mikio Hirabayashi - Perl API of B+ tree was added. - C, C++ and Java APIs of B+ tree were enhanced. - Release: 1.6.4 2003-07-08 Mikio Hirabayashi - Java API of B++ tree was added. - C API of B+ tree was enhanced. - C++ API of B+ tree was enhanced. - Release: 1.6.3 2003-07-05 Mikio Hirabayashi - Debug routines were removed and speed was improved. - No locking mode was added. - Endian converter of Villa was added. - C++ API of B++ tree was added. - Release: 1.6.2 2003-07-03 Mikio Hirabayashi - The advanced API was enhanced to improve its speed. - Makefiles were enhanced for HP-UX. - Release: 1.6.1 2003-06-28 Mikio Hirabayashi - The advanced API for B+ tree database is added. - Release: 1.6.0 2003-06-23 Mikio Hirabayashi - Makefiles were enhanced for Mac OS X. - Release: 1.5.13 2003-06-18 Mikio Hirabayashi - Makefile was enhanced for Solaris and Mac OS X. - Release: 1.5.12 2003-06-06 Mikio Hirabayashi - The utility API was enhanced. - Release: 1.5.11 2003-05-31 Mikio Hirabayashi - The utility API was enhanced. - Release: 1.5.10 2003-05-29 Mikio Hirabayashi - The utility API was changed. - Release: 1.5.9 2003-05-25 Mikio Hirabayashi - Alignment mechanism was simplified. - Release: 1.5.8 2003-05-17 Mikio Hirabayashi - Makefile was updated - Release: 1.5.7 2003-05-16 Mikio Hirabayashi - Test tools were enhanced. - Release: 1.5.6 2003-05-14 Mikio Hirabayashi - Makefile using libtool was added. - Release: 1.5.5 2003-05-12 Mikio Hirabayashi - API for Ruby was enhanced. - Release: 1.5.4 2003-05-08 Mikio Hirabayashi - API for Ruby was added. - Release: 1.5.3 2003-05-04 Mikio Hirabayashi - API for Perl was enhanced. - Release: 1.5.2 2003-04-30 Mikio Hirabayashi - API for Perl was enhanced. - Release: 1.5.1 2003-04-29 Mikio Hirabayashi - API for Perl was added. - Release: 1.5.0 2003-04-25 Mikio Hirabayashi - The package was reorganized to be a GNU package. - Release: 1.4.11 2003-04-21 Mikio Hirabayashi - The utility API was added. - Release: 1.4.10 2003-04-15 Mikio Hirabayashi - Endian converters were added. - Release: 1.4.9 2003-04-12 Mikio Hirabayashi - The GDBM-compatible API was enhanced. - Release: 1.4.8 2003-04-10 Mikio Hirabayashi - Some bugs were fixed and C++ API was enhanced. - Release: 1.4.7 2003-04-09 Mikio Hirabayashi - Coalescence of dead regions and reuse of them were featured. - Release: 1.4.6 2003-04-06 Mikio Hirabayashi - The GDBM-compatible API and the C++ API were enhanced. - Release: 1.4.5 2003-04-04 Mikio Hirabayashi - The API for C++ and the API for Java were enhanced. - Release: 1.4.4 2003-04-02 Mikio Hirabayashi - Documents for C++ was enhanced. - Release: 1.4.3 2003-04-01 Mikio Hirabayashi - The API for Java was enhanced. - Release: 1.4.2 2003-03-23 Mikio Hirabayashi - Makefiles were modified. - Release: 1.4.1 2003-03-23 Mikio Hirabayashi - APIs for C++ and Java was enhanced. - Release: 1.4.0 2003-03-15 Mikio Hirabayashi - The API for C++ was added. - Release: 1.3.2 2003-03-11 Mikio Hirabayashi - The API for Java was supported on Solaris and Windows. - Release: 1.3.1 2003-03-04 Mikio Hirabayashi - The API for Java was added. - Release: 1.3.0 2003-02-23 Mikio Hirabayashi - The GDBM-compatible API was added. - Release: 1.2.0 2003-02-21 Mikio Hirabayashi - Compatibility with NDBM was improved. - Release: 1.1.3 2003-02-18 Mikio Hirabayashi - Optimizing suppoted on Windows. DLL is supported. - Release: 1.1.2 2003-02-15 Mikio Hirabayashi - Windows is now supported. - The compatible API was enhanced. - Release: 1.1.1 2003-02-11 Mikio Hirabayashi - The NDBM-compatible API was added. - Release: 1.1.0 2003-02-08 Mikio Hirabayashi - The initial version. - Release: 1.0.0 qdbm-1.8.78/odeum.h0000644000175000017500000006505510573416530013045 0ustar mikiomikio/************************************************************************************************* * The inverted API of QDBM * Copyright (C) 2000-2007 Mikio Hirabayashi * This file is part of QDBM, Quick Database Manager. * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU * Lesser General Public License as published by the Free Software Foundation; either version * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * You should have received a copy of the GNU Lesser General Public License along with QDBM; if * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. *************************************************************************************************/ #ifndef _ODEUM_H /* duplication check */ #define _ODEUM_H #if defined(__cplusplus) /* export for C++ */ extern "C" { #endif #include #include #include #include #include #include #if defined(_MSC_VER) && !defined(QDBM_INTERNAL) && !defined(QDBM_STATIC) #define MYEXTERN extern __declspec(dllimport) #else #define MYEXTERN extern #endif /************************************************************************************************* * API *************************************************************************************************/ typedef struct { /* type of structure for a database handle */ char *name; /* name of the database directory */ int wmode; /* whether to be writable */ int fatal; /* whether a fatal error occured */ int inode; /* inode of the database directory */ CURIA *docsdb; /* database handle for documents */ CURIA *indexdb; /* database handle for the inverted index */ VILLA *rdocsdb; /* database handle for the reverse dictionary */ CBMAP *cachemap; /* cache for dirty buffers of words */ int cacheasiz; /* total allocated size of dirty buffers */ CBMAP *sortmap; /* map handle for candidates of sorting */ int dmax; /* max number of the document ID */ int dnum; /* number of the documents */ int ldid; /* ID number of the last registered document */ char statechars[256]; /* state of single byte characters */ } ODEUM; typedef struct { /* type of structure for a document handle */ int id; /* ID number */ char *uri; /* uniform resource identifier */ CBMAP *attrs; /* map handle for attrubutes */ CBLIST *nwords; /* list handle for words in normalized form */ CBLIST *awords; /* list handle for words in appearance form */ } ODDOC; typedef struct { /* type of structure for an element of search result */ int id; /* ID number of the document */ int score; /* score of the document */ } ODPAIR; enum { /* enumeration for open modes */ OD_OREADER = 1 << 0, /* open as a reader */ OD_OWRITER = 1 << 1, /* open as a writer */ OD_OCREAT = 1 << 2, /* a writer creating */ OD_OTRUNC = 1 << 3, /* a writer truncating */ OD_ONOLCK = 1 << 4, /* open without locking */ OD_OLCKNB = 1 << 5 /* lock without blocking */ }; /* Get a database handle. `name' specifies the name of a database directory. `omode' specifies the connection mode: `OD_OWRITER' as a writer, `OD_OREADER' as a reader. If the mode is `OD_OWRITER', the following may be added by bitwise or: `OD_OCREAT', which means it creates a new database if not exist, `OD_OTRUNC', which means it creates a new database regardless if one exists. Both of `OD_OREADER' and `OD_OWRITER' can be added to by bitwise or: `OD_ONOLCK', which means it opens a database directory without file locking, or `OD_OLCKNB', which means locking is performed without blocking. The return value is the database handle or `NULL' if it is not successful. While connecting as a writer, an exclusive lock is invoked to the database directory. While connecting as a reader, a shared lock is invoked to the database directory. The thread blocks until the lock is achieved. If `OD_ONOLCK' is used, the application is responsible for exclusion control. */ ODEUM *odopen(const char *name, int omode); /* Close a database handle. `odeum' specifies a database handle. If successful, the return value is true, else, it is false. Because the region of a closed handle is released, it becomes impossible to use the handle. Updating a database is assured to be written when the handle is closed. If a writer opens a database but does not close it appropriately, the database will be broken. */ int odclose(ODEUM *odeum); /* Store a document. `odeum' specifies a database handle connected as a writer. `doc' specifies a document handle. `wmax' specifies the max number of words to be stored in the document database. If it is negative, the number is unlimited. `over' specifies whether the data of the duplicated document is overwritten or not. If it is false and the URI of the document is duplicated, the function returns as an error. If successful, the return value is true, else, it is false. */ int odput(ODEUM *odeum, ODDOC *doc, int wmax, int over); /* Delete a document specified by a URI. `odeum' specifies a database handle connected as a writer. `uri' specifies the string of the URI of a document. If successful, the return value is true, else, it is false. False is returned when no document corresponds to the specified URI. */ int odout(ODEUM *odeum, const char *uri); /* Delete a document specified by an ID number. `odeum' specifies a database handle connected as a writer. `id' specifies the ID number of a document. If successful, the return value is true, else, it is false. False is returned when no document corresponds to the specified ID number. */ int odoutbyid(ODEUM *odeum, int id); /* Retrieve a document specified by a URI. `odeum' specifies a database handle. `uri' specifies the string the URI of a document. If successful, the return value is the handle of the corresponding document, else, it is `NULL'. `NULL' is returned when no document corresponds to the specified URI. Because the handle of the return value is opened with the function `oddocopen', it should be closed with the function `oddocclose'. */ ODDOC *odget(ODEUM *odeum, const char *uri); /* Retrieve a document by an ID number. `odeum' specifies a database handle. `id' specifies the ID number of a document. If successful, the return value is the handle of the corresponding document, else, it is `NULL'. `NULL' is returned when no document corresponds to the specified ID number. Because the handle of the return value is opened with the function `oddocopen', it should be closed with the function `oddocclose'. */ ODDOC *odgetbyid(ODEUM *odeum, int id); /* Retrieve the ID of the document specified by a URI. `odeum' specifies a database handle. `uri' specifies the string the URI of a document. If successful, the return value is the ID number of the document, else, it is -1. -1 is returned when no document corresponds to the specified URI. */ int odgetidbyuri(ODEUM *odeum, const char *uri); /* Check whether the document specified by an ID number exists. `odeum' specifies a database handle. `id' specifies the ID number of a document. The return value is true if the document exists, else, it is false. */ int odcheck(ODEUM *odeum, int id); /* Search the inverted index for documents including a particular word. `odeum' specifies a database handle. `word' specifies a searching word. `max' specifies the max number of documents to be retrieve. `np' specifies the pointer to a variable to which the number of the elements of the return value is assigned. If successful, the return value is the pointer to an array, else, it is `NULL'. Each element of the array is a pair of the ID number and the score of a document, and sorted in descending order of their scores. Even if no document corresponds to the specified word, it is not error but returns an dummy array. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. Note that each element of the array of the return value can be data of a deleted document. */ ODPAIR *odsearch(ODEUM *odeum, const char *word, int max, int *np); /* Get the number of documents including a word. `odeum' specifies a database handle. `word' specifies a searching word. If successful, the return value is the number of documents including the word, else, it is -1. Because this function does not read the entity of the inverted index, it is faster than `odsearch'. */ int odsearchdnum(ODEUM *odeum, const char *word); /* Initialize the iterator of a database handle. `odeum' specifies a database handle. If successful, the return value is true, else, it is false. The iterator is used in order to access every document stored in a database. */ int oditerinit(ODEUM *odeum); /* Get the next key of the iterator. `odeum' specifies a database handle. If successful, the return value is the handle of the next document, else, it is `NULL'. `NULL' is returned when no document is to be get out of the iterator. It is possible to access every document by iteration of calling this function. However, it is not assured if updating the database is occurred while the iteration. Besides, the order of this traversal access method is arbitrary, so it is not assured that the order of string matches the one of the traversal access. Because the handle of the return value is opened with the function `oddocopen', it should be closed with the function `oddocclose'. */ ODDOC *oditernext(ODEUM *odeum); /* Synchronize updating contents with the files and the devices. `odeum' specifies a database handle connected as a writer. If successful, the return value is true, else, it is false. This function is useful when another process uses the connected database directory. */ int odsync(ODEUM *odeum); /* Optimize a database. `odeum' specifies a database handle connected as a writer. If successful, the return value is true, else, it is false. Elements of the deleted documents in the inverted index are purged. */ int odoptimize(ODEUM *odeum); /* Get the name of a database. `odeum' specifies a database handle. If successful, the return value is the pointer to the region of the name of the database, else, it is `NULL'. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. */ char *odname(ODEUM *odeum); /* Get the total size of database files. `odeum' specifies a database handle. If successful, the return value is the total size of the database files, else, it is -1.0. */ double odfsiz(ODEUM *odeum); /* Get the total number of the elements of the bucket arrays in the inverted index. `odeum' specifies a database handle. If successful, the return value is the total number of the elements of the bucket arrays, else, it is -1. */ int odbnum(ODEUM *odeum); /* Get the total number of the used elements of the bucket arrays in the inverted index. `odeum' specifies a database handle. If successful, the return value is the total number of the used elements of the bucket arrays, else, it is -1. */ int odbusenum(ODEUM *odeum); /* Get the number of the documents stored in a database. `odeum' specifies a database handle. If successful, the return value is the number of the documents stored in the database, else, it is -1. */ int oddnum(ODEUM *odeum); /* Get the number of the words stored in a database. `odeum' specifies a database handle. If successful, the return value is the number of the words stored in the database, else, it is -1. Because of the I/O buffer, the return value may be less than the hard number. */ int odwnum(ODEUM *odeum); /* Check whether a database handle is a writer or not. `odeum' specifies a database handle. The return value is true if the handle is a writer, false if not. */ int odwritable(ODEUM *odeum); /* Check whether a database has a fatal error or not. `odeum' specifies a database handle. The return value is true if the database has a fatal error, false if not. */ int odfatalerror(ODEUM *odeum); /* Get the inode number of a database directory. `odeum' specifies a database handle. The return value is the inode number of the database directory. */ int odinode(ODEUM *odeum); /* Get the last modified time of a database. `odeum' specifies a database handle. The return value is the last modified time of the database. */ time_t odmtime(ODEUM *odeum); /* Merge plural database directories. `name' specifies the name of a database directory to create. `elemnames' specifies a list of names of element databases. If successful, the return value is true, else, it is false. If two or more documents which have the same URL come in, the first one is adopted and the others are ignored. */ int odmerge(const char *name, const CBLIST *elemnames); /* Remove a database directory. `name' specifies the name of a database directory. If successful, the return value is true, else, it is false. A database directory can contain databases of other APIs of QDBM, they are also removed by this function. */ int odremove(const char *name); /* Get a document handle. `uri' specifies the URI of a document. The return value is a document handle. The ID number of a new document is not defined. It is defined when the document is stored in a database. */ ODDOC *oddocopen(const char *uri); /* Close a document handle. `doc' specifies a document handle. Because the region of a closed handle is released, it becomes impossible to use the handle. */ void oddocclose(ODDOC *doc); /* Add an attribute to a document. `doc' specifies a document handle. `name' specifies the string of the name of an attribute. `value' specifies the string of the value of the attribute. */ void oddocaddattr(ODDOC *doc, const char *name, const char *value); /* Add a word to a document. `doc' specifies a document handle. `normal' specifies the string of the normalized form of a word. Normalized forms are treated as keys of the inverted index. If the normalized form of a word is an empty string, the word is not reflected in the inverted index. `asis' specifies the string of the appearance form of the word. Appearance forms are used after the document is retrieved by an application. */ void oddocaddword(ODDOC *doc, const char *normal, const char *asis); /* Get the ID number of a document. `doc' specifies a document handle. The return value is the ID number of a document. */ int oddocid(const ODDOC *doc); /* Get the URI of a document. `doc' specifies a document handle. The return value is the string of the URI of a document. */ const char *oddocuri(const ODDOC *doc); /* Get the value of an attribute of a document. `doc' specifies a document handle. `name' specifies the string of the name of an attribute. The return value is the string of the value of the attribute, or `NULL' if no attribute corresponds. */ const char *oddocgetattr(const ODDOC *doc, const char *name); /* Get the list handle contains words in normalized form of a document. `doc' specifies a document handle. The return value is the list handle contains words in normalized form. */ const CBLIST *oddocnwords(const ODDOC *doc); /* Get the list handle contains words in appearance form of a document. `doc' specifies a document handle. The return value is the list handle contains words in appearance form. */ const CBLIST *oddocawords(const ODDOC *doc); /* Get the map handle contains keywords in normalized form and their scores. `doc' specifies a document handle. `max' specifies the max number of keywords to get. `odeum' specifies a database handle with which the IDF for weighting is calculate. If it is `NULL', it is not used. The return value is the map handle contains keywords and their scores. Scores are expressed as decimal strings. Because the handle of the return value is opened with the function `cbmapopen', it should be closed with the function `cbmapclose' if it is no longer in use. */ CBMAP *oddocscores(const ODDOC *doc, int max, ODEUM *odeum); /* Break a text into words in appearance form. `text' specifies the string of a text. The return value is the list handle contains words in appearance form. Words are separated with space characters and such delimiters as period, comma and so on. Because the handle of the return value is opened with the function `cblistopen', it should be closed with the function `cblistclose' if it is no longer in use. */ CBLIST *odbreaktext(const char *text); /* Make the normalized form of a word. `asis' specifies the string of the appearance form of a word. The return value is is the string of the normalized form of the word. Alphabets of the ASCII code are unified into lower cases. Words composed of only delimiters are treated as empty strings. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. */ char *odnormalizeword(const char *asis); /* Get the common elements of two sets of documents. `apairs' specifies the pointer to the former document array. `anum' specifies the number of the elements of the former document array. `bpairs' specifies the pointer to the latter document array. `bnum' specifies the number of the elements of the latter document array. `np' specifies the pointer to a variable to which the number of the elements of the return value is assigned. The return value is the pointer to a new document array whose elements commonly belong to the specified two sets. Elements of the array are sorted in descending order of their scores. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. */ ODPAIR *odpairsand(ODPAIR *apairs, int anum, ODPAIR *bpairs, int bnum, int *np); /* Get the sum of elements of two sets of documents. `apairs' specifies the pointer to the former document array. `anum' specifies the number of the elements of the former document array. `bpairs' specifies the pointer to the latter document array. `bnum' specifies the number of the elements of the latter document array. `np' specifies the pointer to a variable to which the number of the elements of the return value is assigned. The return value is the pointer to a new document array whose elements belong to both or either of the specified two sets. Elements of the array are sorted in descending order of their scores. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. */ ODPAIR *odpairsor(ODPAIR *apairs, int anum, ODPAIR *bpairs, int bnum, int *np); /* Get the difference set of documents. `apairs' specifies the pointer to the former document array. `anum' specifies the number of the elements of the former document array. `bpairs' specifies the pointer to the latter document array of the sum of elements. `bnum' specifies the number of the elements of the latter document array. `np' specifies the pointer to a variable to which the number of the elements of the return value is assigned. The return value is the pointer to a new document array whose elements belong to the former set but not to the latter set. Elements of the array are sorted in descending order of their scores. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. */ ODPAIR *odpairsnotand(ODPAIR *apairs, int anum, ODPAIR *bpairs, int bnum, int *np); /* Sort a set of documents in descending order of scores. `pairs' specifies the pointer to a document array. `pnum' specifies the number of the elements of the document array. */ void odpairssort(ODPAIR *pairs, int pnum); /* Get the natural logarithm of a number. `x' specifies a number. The return value is the natural logarithm of the number. If the number is equal to or less than 1.0, the return value is 0.0. This function is useful when an application calculates the IDF of search results. */ double odlogarithm(double x); /* Get the cosine of the angle of two vectors. `avec' specifies the pointer to one array of numbers. `bvec' specifies the pointer to the other array of numbers. `vnum' specifies the number of elements of each array. The return value is the cosine of the angle of two vectors. This function is useful when an application calculates similarity of documents. */ double odvectorcosine(const int *avec, const int *bvec, int vnum); /* Set the global tuning parameters. `ibnum' specifies the number of buckets for inverted indexes. `idnum' specifies the division number of inverted index. `cbnum' specifies the number of buckets for dirty buffers. `csiz' specifies the maximum bytes to use memory for dirty buffers. The default setting is equivalent to `odsettuning(32749, 7, 262139, 8388608)'. This function should be called before opening a handle. */ void odsettuning(int ibnum, int idnum, int cbnum, int csiz); /* Break a text into words and store appearance forms and normalized form into lists. `odeum' specifies a database handle. `text' specifies the string of a text. `awords' specifies a list handle into which appearance form is store. `nwords' specifies a list handle into which normalized form is store. If it is `NULL', it is ignored. Words are separated with space characters and such delimiters as period, comma and so on. */ void odanalyzetext(ODEUM *odeum, const char *text, CBLIST *awords, CBLIST *nwords); /* Set the classes of characters used by `odanalyzetext'. `odeum' specifies a database handle. `spacechars' spacifies a string contains space characters. `delimchars' spacifies a string contains delimiter characters. `gluechars' spacifies a string contains glue characters. */ void odsetcharclass(ODEUM *odeum, const char *spacechars, const char *delimchars, const char *gluechars); /* Query a database using a small boolean query language. `odeum' specifies a database handle. 'query' specifies the text of the query. `np' specifies the pointer to a variable to which the number of the elements of the return value is assigned. `errors' specifies a list handle into which error messages are stored. If it is `NULL', it is ignored. If successful, the return value is the pointer to an array, else, it is `NULL'. Each element of the array is a pair of the ID number and the score of a document, and sorted in descending order of their scores. Even if no document corresponds to the specified condition, it is not error but returns an dummy array. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. Note that each element of the array of the return value can be data of a deleted document. */ ODPAIR *odquery(ODEUM *odeum, const char *query, int *np, CBLIST *errors); /************************************************************************************************* * features for experts *************************************************************************************************/ /* Get the internal database handle for documents. `odeum' specifies a database handle. The return value is the internal database handle for documents. Note that the the returned handle should not be updated. */ CURIA *odidbdocs(ODEUM *odeum); /* Get the internal database handle for the inverted index. `odeum' specifies a database handle. The return value is the internal database handle for the inverted index. Note that the the returned handle should not be updated. */ CURIA *odidbindex(ODEUM *odeum); /* Get the internal database handle for the reverse dictionary. `odeum' specifies a database handle. The return value is the internal database handle for the reverse dictionary. Note that the the returned handle should not be updated. */ VILLA *odidbrdocs(ODEUM *odeum); /* Set the call back function called in merging. `otcb' specifires the pointer to a function to report outturn. Its first argument is the name of processing function. Its second argument is the handle of the database being processed. Its third argument is ths string of a log message. If it is `NULL', the call back function is cleared. */ void odsetotcb(void (*otcb)(const char *, ODEUM *, const char *)); /* Get the positive one of square roots of a number. `x' specifies a number. The return value is the positive one of square roots of a number. If the number is equal to or less than 0.0, the return value is 0.0. */ double odsquareroot(double x); /* Get the absolute of a vector. `vec' specifies the pointer to an array of numbers. `vnum' specifies the number of elements of the array. The return value is the absolute of a vector. */ double odvecabsolute(const int *vec, int vnum); /* Get the inner product of two vectors. `avec' specifies the pointer to one array of numbers. `bvec' specifies the pointer to the other array of numbers. `vnum' specifies the number of elements of each array. The return value is the inner product of two vectors. */ double odvecinnerproduct(const int *avec, const int *bvec, int vnum); #undef MYEXTERN #if defined(__cplusplus) /* export for C++ */ } #endif #endif /* duplication check */ /* END OF FILE */ qdbm-1.8.78/lab/0000755000175000017500000000000010174674434012314 5ustar mikiomikioqdbm-1.8.78/lab/testdata.tsv0000644000175000017500000006104510174674366014675 0ustar mikiomikio1 one 2 two 3 three 4 four 5 five 6 six 7 seven 8 eight 9 nine 10 ten longval This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. This is a pen. longkey euc-jp ¤³¤ì¤Ï¥Ú¥ó¤Ç¤¹¡£¤¢¤ì¤â¥Ú¥ó¤Ç¤¹¡£»ä¤ÏÊ¿ÎÓ´´Íº¤Ç¤¹¡£QDBM¤Ï»È¤¤¤ä¤¹¤¤¤Ç¤¹¡£ foo first occurence of duplication foo last occurence of duplication emptykey emptyval x xxxxx xx xxxx xxx xxx xxxx xx xxxxx x qdbm-1.8.78/lab/texttohtml0000755000175000017500000000147010123611034014435 0ustar mikiomikio#! /bin/sh #================================================================ # texttohtml # Escape meta character of HTML #================================================================ # print header cat <<__EOF Generated by texttohtml
__EOF


# print body
cat $1 | sed -e 's/&/\&/g' -e 's//\>/g'


# print footer
cat <<__EOF
__EOF # exit normally exit 0 # END OF FILE qdbm-1.8.78/lab/Makefile0000644000175000017500000000241410043333227013740 0ustar mikiomikio# Makefile for developer's utility #================================================================ # Setting variables #================================================================ # Generic settings SHELL = /bin/sh # Targets MYBINS = hashtest sorttest fmtcnv031127 # Building binaries CC = gcc CPPFLAGS = -I.. -I/usr/local/include -DNDEBUG CFLAGS = -Wall -ansi -pedantic -g LDFLAGS = -L.. -L/usr/local/lib -lqdbm #================================================================ # Suffix rules #================================================================ .SUFFIXES : .SUFFIXES : .c .o .c.o : $(CC) $(CPPFLAGS) $(CFLAGS) -c $< #================================================================ # Actions #================================================================ all : $(MYBINS) clean : rm -rf $(MYBINS) *.o *.exe a.out gmon.out leak.log *~ distclean : clean #================================================================ # Building binaries #================================================================ hashtest : hashtest.o $(CC) $(CFLAGS) -o $@ hashtest.o $(LDFLAGS) sorttest : sorttest.o $(CC) $(CFLAGS) -o $@ sorttest.o $(LDFLAGS) fmtcnv031127 : fmtcnv031127.o $(CC) $(CFLAGS) -o $@ fmtcnv031127.o $(LDFLAGS) # END OF FILE qdbm-1.8.78/lab/tabcheck0000755000175000017500000000132710050443362013774 0ustar mikiomikio#! /bin/sh #================================================================ # tabcheck # Find files including dispensable tab and space characters #================================================================ # set variables regex='(\.h|\.c|\.cc|\.cpp|\.cxx|\.java|\.pl|\.pm|\.pod|\.rb|\.rd)$' tabcode=`printf '\t'` # find tab find . -type f | egrep $regex | while read file do printf 'Checking %s ... ' $file err=0 if grep "$tabcode" $file > /dev/null then printf '### !!! TAB FOUND !!! ###' err=1 fi if grep ' $' $file > /dev/null then printf '### !!! TAILING SPACE FOUND !!! ###' err=1 fi [ "$err" = 0 ] && printf 'ok' printf '\n' done # exit normally exit 0 # END OF FILE qdbm-1.8.78/lab/hashtest.c0000644000175000017500000000716510355663555014317 0ustar mikiomikio/************************************************************************************************* * Test unit for hash functions *************************************************************************************************/ #include #include #include #include #define RECBUFSIZ 32 #define RANDDATAMIN 4 #define RANDDATAMAX 12 /* function prototypes */ int main(int argc, char **argv); void usage(const char *progname); int setrandstr(char *buf); void printcol(const char *name, int (*hfunc)(const char *, int), int rnum, int bnum); int dpfirsthash(const char *kbuf, int ksiz); int dpsecondhash(const char *kbuf, int ksiz); int dpthirdhash(const char *kbuf, int ksiz); /* main routine */ int main(int argc, char **argv){ int rnum, bnum, i, len; char buf[RECBUFSIZ]; rnum = argc > 1 ? atoi(argv[1]) : -1; bnum = argc > 2 ? atoi(argv[2]) : -1; srand(time(NULL)); if(rnum > 0 && bnum > 0){ printf("number of records: %d\n", rnum); printf("number of buckets: %d\n", bnum); printcol("dpfirsthash", dpfirsthash, rnum, bnum); printcol("dpsecondhash", dpsecondhash, rnum, bnum); printcol("dpthirdhash", dpthirdhash, rnum, bnum); } else if(rnum > 0){ for(i = 1; i < rnum; i++){ len = sprintf(buf, "%X", i); printf("%s", buf); printf("\t%10d", dpfirsthash(buf, len)); printf("\t%10d", dpsecondhash(buf, len)); printf("\t%10d", dpthirdhash(buf, len)); printf("\n"); } } else { usage(argv[0]); } return 0; } /* show usage and exit */ void usage(const char *progname){ fprintf(stderr, "%s: test unit for hash functions\n\n", progname); fprintf(stderr, "usage:\n"); fprintf(stderr, " %s rnum bnum : print collision rate\n", progname); fprintf(stderr, " %s rnum : print values\n", progname); exit(1); } /* set randum string and return its length */ int setrandstr(char *buf){ int i, len; len = rand() % (RANDDATAMAX - RANDDATAMIN) + RANDDATAMIN + 1; for(i = 0; i < len; i++){ buf[i] = rand() % 256; } buf[len] = '\0'; return len; } /* print collision rate of each hash functioon */ void printcol(const char *name, int (*hfunc)(const char *, int), int rnum, int bnum){ int *array, i, len, col; char buf[RECBUFSIZ]; if(!(array = calloc(bnum, sizeof(int)))) return; for(i = 1; i <= rnum; i++){ len = setrandstr(buf); array[hfunc(buf, len) % bnum]++; } col = 0; for(i = 0; i < bnum; i++){ if(array[i] > 1) col += array[i] - 1; } printf("collision rate: %5.2f%% (%8d) by %s\n", ((double)col / (double)rnum) * 100.0, col, name); free(array); } /* hash function to select a bucket element */ int dpfirsthash(const char *kbuf, int ksiz){ const unsigned char *p; unsigned int sum; int i; assert(kbuf && ksiz >= 0); p = (const unsigned char *)kbuf; sum = 751; for(i = 0; i < ksiz; i++){ sum = sum * 31 + p[i]; } return (sum * 87767623) & 0x7FFFFFFF; } /* hash function to select a right/left node of binary search tree */ int dpsecondhash(const char *kbuf, int ksiz){ const unsigned char *p; unsigned int sum; int i; assert(kbuf && ksiz >= 0); p = (const unsigned char *)kbuf; sum = 19780211; for(i = ksiz - 1; i >= 0; i--){ sum = sum * 37 + p[i]; } return (sum * 43321879) & 0x7FFFFFFF; } /* hash function for its applications */ int dpthirdhash(const char *kbuf, int ksiz){ const unsigned char *p; unsigned int sum; int i; assert(kbuf && ksiz >= 0); p = (const unsigned char *)kbuf; sum = 774831917; for(i = ksiz - 1; i >= 0; i--){ sum = sum * 29 + p[i]; } return (sum * 5157883) & 0x7FFFFFFF; } /* END OF FILE */ qdbm-1.8.78/lab/stepcount0000755000175000017500000000061710050443366014261 0ustar mikiomikio#! /bin/sh #================================================================ # stepcount # Find files including dispensable tab characters #================================================================ # set variables regex='(\.h|\.c|\.cc|\.java|\.pl|\.pm|\.xs|\.rb|\.js)$' # count steps files=`find . -type f | egrep $regex` wc -l $files | sort -n # exit normally exit 0 # END OF FILE qdbm-1.8.78/lab/diffcheck0000755000175000017500000000152210123611014014123 0ustar mikiomikio#! /bin/sh #================================================================ # diffcheck # List files different from ones of another version #================================================================ # set variables progexts='\.in|\.h|\.c|\.cc|\.cpp|\.cxx|\.java|\.pl|\.pm|\.pod|\.rb|\.rd' docexts='\.[1-9]|spex\.html|\spex-ja\.html|\.txt' regex="($progexts|$docexts)\$" # check arguments if [ $# != 1 ] then printf 'diffcheck: usage: diffcheck directory_of_oldversion\n' 1>&2 exit 1 fi # diff files find . -type f | egrep $regex | while read file do old=`printf '%s\n' "$file" | sed 's/^\.\///'` printf 'Checking %s and %s ... ' "$file" "$1/$old" res=`diff -q "$file" "$1/$old"` if [ -z "$res" ] then printf 'same\n' else printf '### !!! DIFFERENT !!! ###\n' fi done # exit normally exit 0 # END OF FILE qdbm-1.8.78/lab/sorttest.c0000644000175000017500000000356610355663555014364 0ustar mikiomikio/************************************************************************************************* * Test unit for sorting functions *************************************************************************************************/ #include #include #include #include #include #define INPUTBIAS 0 /* function prototypes */ int main(int argc, char **argv); void usage(const char *progname); int strpcmp(const void *ap, const void *bp); /* main routine */ int main(int argc, char **argv){ int i, rnum, len; char **ivector, buf[32]; if(argc != 3) usage(argv[0]); if((rnum = atoi(argv[2])) < 1) usage(argv[0]); if(!strchr("ishqQp", argv[1][0])) usage(argv[0]); ivector = cbmalloc(rnum * sizeof(ivector[0])); for(i = 0; i < rnum; i++){ len = sprintf(buf, "%08d", rand() % rnum + i * INPUTBIAS + 1); ivector[i] = cbmemdup(buf, len); } switch(argv[1][0]){ case 'i': cbisort(ivector, rnum, sizeof(ivector[0]), strpcmp); break; case 's': cbssort(ivector, rnum, sizeof(ivector[0]), strpcmp); break; case 'h': cbhsort(ivector, rnum, sizeof(ivector[0]), strpcmp); break; case 'q': cbqsort(ivector, rnum, sizeof(ivector[0]), strpcmp); break; case 'Q': qsort(ivector, rnum, sizeof(ivector[0]), strpcmp); break; } if(strchr(argv[1], 'p')){ for(i = 0; i < rnum; i++){ printf("%s\n", ivector[i]); free(ivector[i]); } } else { for(i = 0; i < rnum; i++){ free(ivector[i]); } } free(ivector); return 0; } /* show usage and exit */ void usage(const char *progname){ fprintf(stderr, "%s: usage: %s i|s|h|q|Q|p|ip|sp|hp|qp|Qp rnum\n", progname, progname); exit(1); } /* comparing function */ int strpcmp(const void *ap, const void *bp){ char *a, *b; a = *(char **)ap; b = *(char **)bp; return strcmp(a, b); } /* END OF FILE */ qdbm-1.8.78/lab/ccdoc0000755000175000017500000001433710050443402013303 0ustar mikiomikio#! /bin/sh #================================================================ # ccdoc # Document generator for C/C++ sources #================================================================ # set variables progname='ccdoc' stylefile='ccstyle.css' indexfile='index.html' lang='en' charset='ISO-8859-1' targets='' sufregxp='(\.h|\.c|\.cc|\.cxx|\.cpp)$' outdir='srcdoc' title='Source Documents' overview='' numopt='' dark='no' # function to show usage and exit usage(){ printf 'usage: %s [options] sourcefiles ...\n' "$progname" printf 'options:\n' 2>&1 printf ' -l lang assign the language of documents\n' 2>&1 printf ' -cs charset assign the charcter set of documents\n' 2>&1 printf ' -t title assign the title of the index file\n' 2>&1 printf ' -d directory assign the directory in which documents are stored\n' 2>&1 printf ' -ov file assign the HTML file for overview\n' 2>&1 printf ' -n number all output lines\n' 2>&1 printf ' -dark set the style dark\n' 2>&1 exit 1; } # check dependency if source-highlight --version > /dev/null then true else printf '%s: requires GNU source-highlight\n' "$progname" 2>&1 exit 1 fi # parse arguments while true do if printf '%s\n' "$1" | grep '^-' > /dev/null then case "$1" in '-l') [ $# -le 1 ] && usage ; shift ; lang="$1" ;; '-cs') [ $# -le 1 ] && usage ; shift ; charset="$1" ;; '-t') [ $# -le 1 ] && usage ; shift ; title="$1" ;; '-d') [ $# -le 1 ] && usage ; shift ; outdir="$1" ;; '-ov') [ $# -le 1 ] && usage ; shift ; overview="$1" ;; '-n') numopt='-n' ;; '-dark') dark='yes' ;; *) usage ;; esac else targets="$targets $1" fi if [ $# -lt 1 ] then break else shift fi done targets=`printf '%s' "$targets" | sed -e 's/^ *//' -e 's/^ *$//'` if [ -z "$targets" ] then usage fi # find target files printf 'finding targets ... ' tfiles="" for file in $targets do if [ -f "$file" ] then tfiles="$tfiles $file" elif [ -d "$file" ] then tfiles="$tfiles `find $file -print | egrep $sufregxp | sed 's/^\.\///' | sort`" else printf '%s: %s: not found\n' "$progname" "$file" 2>&1 exit 1 fi done printf 'ok\n' # create the target directory printf 'creating %s ... ' "$outdir" mkdir -p "$outdir" [ $? != 0 ] && exit 1 printf 'ok\n' # create the index file printf 'creating %s ... ' "$outdir/$indexfile" cat << __EOF > "$outdir/$indexfile" $title

$title


__EOF if [ -n "$overview" ] then printf '

Overview

\n' >> "$outdir/$indexfile" cat "$overview" >> "$outdir/$indexfile" if [ $? != 0 ] then printf '%s: warning: %s: cannot write overview\n' "$progname" "$outdir/$indexfile" 2>&1 fi printf '
\n' >> "$outdir/$indexfile" fi printf '

Sources

\n' >> "$outdir/$indexfile" printf '
    \n' >> "$outdir/$indexfile" for file in $tfiles do outfile="$file.html" printf '
  • %s
  • \n' "$outfile" "$file" >> "$outdir/$indexfile" done printf '
\n' >> "$outdir/$indexfile" if [ $? != 0 ] then printf '%s: %s: cannot create\n' "$progname" "$outdir/$indexfile" 2>&1 exit 1 fi version=`source-highlight --version | head -n 1` cat << __EOF >> "$outdir/$indexfile"
Generated by $progname using $version.
__EOF if [ $? != 0 ] then printf '%s: %s: cannot create\n' "$progname" "$outdir/$indexfile" 2>&1 exit 1 fi printf 'ok\n' # create the style file printf 'creating %s ... ' "$outdir/$stylefile" if [ "$dark" = "yes" ] then cat << __EOF > "$outdir/$stylefile" body { background-color: #002222; color: #667788; margin: 0em 0em; padding: 0.5em 0.8em; } p,div { margin: 1em 2em; } p { text-indent: 0.8em; } a:link,a:visited,a:active { text-decoration: none; color: #88aaff; } a:hover { text-decoration: underline; color: #66eeff; } pre { margin: 0em 0em; padding: 0em 0em; } .normal { color: #ddeeff; } .comment { color: #bb1100; } .preproc { color: #884488; } .function { color: #88ddbb; } .keyword { color: #4488ee; } .type { color: #88bbff; } .string { color: #8899aa; } .number,.symbol,.cbracket { color: #ccddee; } .note { text-align: right; margin: 0.2em 0.2em; color: #8899aa; } h1,h2,h3,p,div,li { color: #ddeeff; } strong { color: #eeee99; } __EOF else cat << __EOF > "$outdir/$stylefile" body { background-color: #ffffff; color: #888888; margin: 0em 0em; padding: 0.5em 0.8em; } p,div { margin: 1em 2em; } p { text-indent: 0.8em; } a:link,a:visited,a:active { text-decoration: none; color: #0022aa; } a:hover { text-decoration: underline; color: #0066ff; } pre { margin: 0em 0em; padding: 0em 0em; } .normal { color: #111111; } .comment { color: #119966; } .preproc { color: #cc2200; } .function { color: #5500bb; } .keyword { color: #0022ff; } .type { color: #003399; } .string { color: #555555; } .number,.symbol,.cbracket { color: #333333; } .note { text-align: right; margin: 0.2em 0.2em; color: #555555} h1,h2,h3,p,div,li { color: #111111; } strong { color: #6600bb; } __EOF fi if [ $? != 0 ] then printf '%s: %s: cannot create\n' "$progname" "$outdir/$stylefile" 2>&1 exit 1 fi printf 'ok\n' # create documents of targets for file in $tfiles do outfile="$file.html" if printf '%s' "$file" | grep '/' > /dev/null then subdir=`printf '%s' "$file" | sed 's/\/[^\/]*$//'` if [ -d "$outdir/$subdir" ] then [ "$subdir" != "." ] && rm -f "$outdir/$subdir/$stylefile" else mkdir -p "$outdir/$subdir" fi [ -f "$outdir/$subdir/$stylefile" ] || cp -f "$outdir/$stylefile" "$outdir/$subdir" fi printf 'creating %s ... ' "$outdir/$outfile" source-highlight -s cpp -f xhtml -d -T "$file ($title)" -c "$stylefile" $numopt < "$file" |\ sed -e "1,13 s///" \ -e "1,13 s/charset=.*\\/>/charset=$charset\" \\/>/" > "$outdir/$outfile" [ $? != 0 ] && exit 1 printf 'ok\n' done # exit normally printf 'all ok\n' exit 0 # END OF FILE qdbm-1.8.78/lab/fmtcnv031127.c0000644000175000017500000000251710355663555014443 0ustar mikiomikio/************************************************************************************************* * Format converter from older than 2003-11-27 to latest *************************************************************************************************/ #include #include #define HEADSIZ 48 #define OLDFSIZOFF 16 #define OLDBNUMOFF 24 #define OLDRNUMOFF 32 #define NEWFLAGSOFF 16 #define NEWFSIZOFF 24 #define NEWBNUMOFF 32 #define NEWRNUMOFF 40 /* function prototypes */ int main(int argc, char **argv); /* main routine */ int main(int argc, char **argv){ char head[HEADSIZ]; int i, vb, zb, flags, fsiz, bnum, rnum, c; vb = 0; zb = 0; for(i = 1; i < argc; i++){ if(!strcmp(argv[i], "-v")) vb = 1; if(!strcmp(argv[i], "-z")) zb = 1; } for(i = 0; i < HEADSIZ; i++){ head[i] = getchar(); } fsiz = *(int *)(head + OLDFSIZOFF); bnum = *(int *)(head + OLDBNUMOFF); rnum = *(int *)(head + OLDRNUMOFF); flags = 0; if(vb) flags |= 1 << 0; if(zb) flags |= 1 << 1; *(int *)(head + NEWFLAGSOFF) = flags; *(int *)(head + NEWFSIZOFF) = fsiz; *(int *)(head + NEWBNUMOFF) = bnum; *(int *)(head + NEWRNUMOFF) = rnum; for(i = 0; i < HEADSIZ; i++){ putchar(head[i]); } while((c = getchar()) != EOF){ putchar(c); } return 0; } /* END OF FILE */ qdbm-1.8.78/lab/edswap0000755000175000017500000000103510165571124013514 0ustar mikiomikio#! /bin/sh #================================================================ # edswap # Swap strings with ed command #================================================================ # check arguments if [ $# -lt 3 ] then printf 'edswap: usage: edswap regex string files...\n' 1>&2 exit 1 fi # make expressions bef=`printf "$1" | sed 's/\//\\\\\//g'` ; shift aft=$1 ; shift # edit files while [ -n "$1" ] do printf "== $1 ==\n" printf "1,\$ s/$bef/$aft/g\nw\n" | ed "$1" shift done # exit normally exit 0 # END OF FILE qdbm-1.8.78/lab/README0000644000175000017500000000254410165570345013175 0ustar mikiomikio================================================================ Utilities for test and experiment ================================================================ - hashtest This command is used in order to see performance of hash functions. - sorttest This command is used in order to see performance of sorting functions. - fmtcnv031127 This command is used in order to convert a database file from older format than 1.7.13 to the latest format. Usage for a database of Depot: fmtcnv031127 < old > new Usage for a database of Villa: fmtcnv031127 -v < old > new Usage for a database of Villa (deflated): fmtcnv031127 -v -z < old > new - setbdflush This command is used in order to set the device file `bdflush' of Linux to see the best performance of QDBM. - tabcheck This command is used in order to check whether tab or tailing space is in source files. - diffcheck This command is used in order to see difference of each file in two directories. - stepcount This command is used in order to count speps of source files. - edswap This command is used in order to swap strings with ed command. - ccdoc This command is used in order to create documents about source code using GNU source-highlight. - texttohtml This command is used in order to convert plain text to HTML. == END OF FILE == qdbm-1.8.78/lab/setbdflush0000755000175000017500000000070010060635675014400 0ustar mikiomikio#! /bin/sh #================================================================ # setbdflush # Setting the parameters of kernel daemon to flush dirty buffers #================================================================ # show previous setting printf 'old value:\n ' sysctl vm.bdflush | tr '\t' ' ' # set new parameters printf 'current value:\n ' sysctl -w "vm.bdflush=80 1000 0 0 0 10000 100 0 0" # exit normally exit 0 # END OF FILE qdbm-1.8.78/hovel.h0000644000175000017500000003056710573416530013051 0ustar mikiomikio/************************************************************************************************* * The GDBM-compatible API of QDBM * Copyright (C) 2000-2007 Mikio Hirabayashi * This file is part of QDBM, Quick Database Manager. * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU * Lesser General Public License as published by the Free Software Foundation; either version * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * You should have received a copy of the GNU Lesser General Public License along with QDBM; if * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. *************************************************************************************************/ #ifndef _HOVEL_H /* duplication check */ #define _HOVEL_H #if defined(__cplusplus) /* export for C++ */ extern "C" { #endif #include #include #include #include #include #if defined(_MSC_VER) && !defined(QDBM_INTERNAL) && !defined(QDBM_STATIC) #define MYEXTERN extern __declspec(dllimport) #else #define MYEXTERN extern #endif /************************************************************************************************* * API *************************************************************************************************/ enum { /* enumeration for error codes */ GDBM_NO_ERROR, /* no error */ GDBM_MALLOC_ERROR, /* malloc error */ GDBM_BLOCK_SIZE_ERROR, /* block size error */ GDBM_FILE_OPEN_ERROR, /* file open error */ GDBM_FILE_WRITE_ERROR, /* file write error */ GDBM_FILE_SEEK_ERROR, /* file seek error */ GDBM_FILE_READ_ERROR, /* file read error */ GDBM_BAD_MAGIC_NUMBER, /* bad magic number */ GDBM_EMPTY_DATABASE, /* empty database */ GDBM_CANT_BE_READER, /* can't be reader */ GDBM_CANT_BE_WRITER, /* can't be writer */ GDBM_READER_CANT_DELETE, /* reader can't delete */ GDBM_READER_CANT_STORE, /* reader can't store */ GDBM_READER_CANT_REORGANIZE, /* reader can't reorganize */ GDBM_UNKNOWN_UPDATE, /* unknown update */ GDBM_ITEM_NOT_FOUND, /* item not found */ GDBM_REORGANIZE_FAILED, /* reorganize failed */ GDBM_CANNOT_REPLACE, /* cannot replace */ GDBM_ILLEGAL_DATA, /* illegal data */ GDBM_OPT_ALREADY_SET, /* option already set */ GDBM_OPT_ILLEGAL /* option illegal */ }; typedef int gdbm_error; /* type of error codes */ typedef struct { /* type of structure for a database handle */ DEPOT *depot; /* internal database handle of Depot */ CURIA *curia; /* internal database handle of Curia */ int syncmode; /* whether to be besyncronous mode */ } GDBM; typedef GDBM *GDBM_FILE; /* type of pointer to a database handle */ typedef struct { /* type of structure for a key or a value */ char *dptr; /* pointer to the region */ size_t dsize; /* size of the region */ } datum; enum { /* enumeration for open modes */ GDBM_READER = 1 << 0, /* open as a reader */ GDBM_WRITER = 1 << 1, /* open as a writer */ GDBM_WRCREAT = 1 << 2, /* a writer creating */ GDBM_NEWDB = 1 << 3, /* a writer creating and truncating */ GDBM_SYNC = 1 << 4, /* syncronous mode */ GDBM_NOLOCK = 1 << 5, /* no lock mode */ GDBM_LOCKNB = 1 << 6, /* non-blocking lock mode */ GDBM_FAST = 1 << 7, /* fast mode */ GDBM_SPARSE = 1 << 8 /* create as sparse file */ }; enum { /* enumeration for write modes */ GDBM_INSERT, /* keep an existing value */ GDBM_REPLACE /* overwrite an existing value */ }; enum { /* enumeration for options */ GDBM_CACHESIZE, /* set cache size */ GDBM_FASTMODE, /* set fast mode */ GDBM_SYNCMODE, /* set syncronous mode */ GDBM_CENTFREE, /* set free block pool */ GDBM_COALESCEBLKS /* set free block marging */ }; /* String containing the version information. */ MYEXTERN char *gdbm_version; /* Last happened error code. */ #define gdbm_errno (*gdbm_errnoptr()) /* Get a message string corresponding to an error code. `gdbmerrno' specifies an error code. The return value is the message string of the error code. The region of the return value is not writable. */ char *gdbm_strerror(gdbm_error gdbmerrno); /* Get a database handle after the fashion of GDBM. `name' specifies a name of a database. `read_write' specifies the connection mode: `GDBM_READER' as a reader, `GDBM_WRITER', `GDBM_WRCREAT' and `GDBM_NEWDB' as a writer. `GDBM_WRCREAT' makes a database file or directory if it does not exist. `GDBM_NEWDB' makes a new database even if it exists. You can add the following to writer modes by bitwise or: `GDBM_SYNC', `GDBM_NOLOCK', `GDBM_LCKNB', `GDBM_FAST', and `GDBM_SPARSE'. `GDBM_SYNC' means a database is synchronized after every updating method. `GDBM_NOLOCK' means a database is opened without file locking. `GDBM_LOCKNB' means file locking is performed without blocking. `GDBM_FAST' is ignored. `GDBM_SPARSE' is an original mode of QDBM and makes database a sparse file. `mode' specifies a mode of a database file or a database directory as the one of `open' or `mkdir' call does. `bnum' specifies the number of elements of each bucket array. If it is not more than 0, the default value is specified. `dnum' specifies the number of division of the database. If it is not more than 0, the returning handle is created as a wrapper of Depot, else, it is as a wrapper of Curia. The return value is the database handle or `NULL' if it is not successful. If the database already exists, whether it is one of Depot or Curia is measured automatically. */ GDBM_FILE gdbm_open(char *name, int block_size, int read_write, int mode, void (*fatal_func)(void)); /* Get a database handle after the fashion of QDBM. `name' specifies a name of a database. `read_write' specifies the connection mode: `GDBM_READER' as a reader, `GDBM_WRITER', `GDBM_WRCREAT' and `GDBM_NEWDB' as a writer. `GDBM_WRCREAT' makes a database file or directory if it does not exist. `GDBM_NEWDB' makes a new database even if it exists. You can add the following to writer modes by bitwise or: `GDBM_SYNC', `GDBM_NOLOCK', `GDBM_LOCKNB', `GDBM_FAST', and `GDBM_SPARSE'. `GDBM_SYNC' means a database is synchronized after every updating method. `GDBM_NOLOCK' means a database is opened without file locking. `GDBM_LOCKNB' means file locking is performed without blocking. `GDBM_FAST' is ignored. `GDBM_SPARSE' is an original mode of QDBM and makes database sparse files. `mode' specifies a mode of a database file as the one of `open' or `mkdir' call does. `bnum' specifies the number of elements of each bucket array. If it is not more than 0, the default value is specified. `dnum' specifies the number of division of the database. If it is not more than 0, the returning handle is created as a wrapper of Depot, else, it is as a wrapper of Curia. `align' specifies the basic size of alignment. The return value is the database handle or `NULL' if it is not successful. */ GDBM_FILE gdbm_open2(char *name, int read_write, int mode, int bnum, int dnum, int align); /* Close a database handle. `dbf' specifies a database handle. Because the region of the closed handle is released, it becomes impossible to use the handle. */ void gdbm_close(GDBM_FILE dbf); /* Store a record. `dbf' specifies a database handle connected as a writer. `key' specifies a structure of a key. `content' specifies a structure of a value. `flag' specifies behavior when the key overlaps, by the following values: `GDBM_REPLACE', which means the specified value overwrites the existing one, `GDBM_INSERT', which means the existing value is kept. The return value is 0 if it is successful, 1 if it gives up because of overlaps of the key, -1 if other error occurs. */ int gdbm_store(GDBM_FILE dbf, datum key, datum content, int flag); /* Delete a record. `dbf' specifies a database handle connected as a writer. `key' specifies a structure of a key. The return value is 0 if it is successful, -1 if some errors occur. */ int gdbm_delete(GDBM_FILE dbf, datum key); /* Retrieve a record. `dbf' specifies a database handle. `key' specifies a structure of a key. The return value is a structure of the result. If a record corresponds, the member `dptr' of the structure is the pointer to the region of the value. If no record corresponds or some errors occur, `dptr' is `NULL'. Because the region pointed to by `dptr' is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. */ datum gdbm_fetch(GDBM_FILE dbf, datum key); /* Check whether a record exists or not. `dbf' specifies a database handle. `key' specifies a structure of a key. The return value is true if a record corresponds and no error occurs, or false, else, it is false. */ int gdbm_exists(GDBM_FILE dbf, datum key); /* Get the first key of a database. `dbf' specifies a database handle. The return value is a structure of the result. If a record corresponds, the member `dptr' of the structure is the pointer to the region of the first key. If no record corresponds or some errors occur, `dptr' is `NULL'. Because the region pointed to by `dptr' is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. */ datum gdbm_firstkey(GDBM_FILE dbf); /* Get the next key of a database. `dbf' specifies a database handle. The return value is a structure of the result. If a record corresponds, the member `dptr' of the structure is the pointer to the region of the next key. If no record corresponds or some errors occur, `dptr' is `NULL'. Because the region pointed to by `dptr' is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. */ datum gdbm_nextkey(GDBM_FILE dbf, datum key); /* Synchronize updating contents with the file and the device. `dbf' specifies a database handle connected as a writer. */ void gdbm_sync(GDBM_FILE dbf); /* Reorganize a database. `dbf' specifies a database handle connected as a writer. If successful, the return value is 0, else -1. */ int gdbm_reorganize(GDBM_FILE dbf); /* Get the file descriptor of a database file. `dbf' specifies a database handle connected as a writer. The return value is the file descriptor of the database file. If the database is a directory the return value is -1. */ int gdbm_fdesc(GDBM_FILE dbf); /* No effect. `dbf' specifies a database handle. `option' is ignored. `size' is ignored. The return value is 0. The function is only for compatibility. */ int gdbm_setopt(GDBM_FILE dbf, int option, int *value, int size); /************************************************************************************************* * features for experts *************************************************************************************************/ /* Get the pointer of the last happened error code. */ int *gdbm_errnoptr(void); #undef MYEXTERN #if defined(__cplusplus) /* export for C++ */ } #endif #endif /* duplication check */ /* END OF FILE */ qdbm-1.8.78/qdbm.spec.in0000644000175000017500000001337311426313670013762 0ustar mikiomikio#================================================================ # RPM Specification for QDBM #================================================================ %define name @PACKAGE_NAME@ %define version @PACKAGE_VERSION@ %define release 1 %define libver @LIBVER@ %define librev @LIBREV@ %define disturl http://fallabs.com/qdbm/ %define homeurl http://fallabs.com/qdbm/ Summary: Quick Database Manager Name: %{name} Version: %{version} Release: %{release} Source: %{disturl}%{name}-%{version}.tar.gz Copyright: LGPL Group: Development/Libraries Packager: Mikio Hirabayashi Distribution: Private Vendor: Private Url: %{homeurl} Requires: zlib BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root %description QDBM is an embeded database library compatible with GDBM and NDBM. It features hash database and B+ tree database and is developed referring to GDBM for the purpose of the following three points: higher processing speed, smaller size of a database file, and simpler API. This package includes APIs for C, C++, and Java. CGI scripts are also contained. APIs for Perl and Ruby should be installed with a source package. %package devel Summary: Headers, libraries, utilities and documentation for QDBM Group: Development/Libraries Requires: %{name} = %{version} %description devel This package contains header files and libraries needed to develop programs using the QDBM library. Some utility commands are also provided. %package plus Summary: C++ libraries for QDBM Group: Development/Libraries Requires: %{name} = %{version} %description plus This package contains libraries needed to develop and run programs using the QDBM C++ bindings. %package java Summary: Java libraries for QDBM Group: Development/Libraries Requires: %{name} = %{version} %description java This package contains libraries needed to develop and run programs using the QDBM Java bindings. %package cgi Summary: CGI scripts with QDBM Group: Development/Libraries Requires: %{name} = %{version} %description cgi This package contains CGI scripts with QDBM, for administration of databases, file uploading, and full-text search. %prep rm -rf $RPM_BUILD_ROOT %setup -q %build ( cd . ; %{configure} --prefix=%{_usr} --mandir=%{_mandir} \ --enable-stable --enable-zlib --enable-iconv --enable-pthread ; make ) ( cd plus ; %{configure} --prefix=%{_usr} --mandir=%{_mandir} ; make ) ( cd java ; %{configure} --prefix=%{_usr} --mandir=%{_mandir} ; make ) ( cd cgi ; %{configure} --prefix=%{_usr} --mandir=%{_mandir} ; make ) %install rm -rf $RPM_BUILD_ROOT ( cd . ; make DESTDIR=$RPM_BUILD_ROOT install-strip ) ( cd plus ; make DESTDIR=$RPM_BUILD_ROOT install-strip ) ( cd java ; make DESTDIR=$RPM_BUILD_ROOT install ) ( cd cgi ; make DESTDIR=$RPM_BUILD_ROOT install-strip ) ( mkdir -p $RPM_BUILD_ROOT%{_datadir}/doc/qdbm && \ cd $RPM_BUILD_ROOT%{_usr}/share/qdbm && \ cp -Rf spex-ja.html spex.html COPYING ChangeLog NEWS THANKS \ plus/xspex.html plus/xspex-ja.html plus/xapidoc \ java/jspex.html java/jspex-ja.html java/japidoc \ cgi/cgispex-ja.html cgi/cgispex.html $RPM_BUILD_ROOT%{_datadir}/doc/qdbm ) %clean rm -rf $RPM_BUILD_ROOT %files %defattr(-,root,root) %{_libdir}/libqdbm.so.%{libver}.%{librev}.0 %{_libdir}/libqdbm.so.%{libver} %{_libdir}/libqdbm.so %files devel %defattr(-,root,root) %{_includedir}/depot.h %{_includedir}/curia.h %{_includedir}/relic.h %{_includedir}/hovel.h %{_includedir}/cabin.h %{_includedir}/villa.h %{_includedir}/vista.h %{_includedir}/odeum.h %{_libdir}/libqdbm.a %{_bindir}/dpmgr %{_bindir}/dptest %{_bindir}/dptsv %{_bindir}/crmgr %{_bindir}/crtest %{_bindir}/crtsv %{_bindir}/rlmgr %{_bindir}/rltest %{_bindir}/hvmgr %{_bindir}/hvtest %{_bindir}/cbtest %{_bindir}/cbcodec %{_bindir}/vlmgr %{_bindir}/vltest %{_bindir}/vltsv %{_bindir}/odmgr %{_bindir}/odtest %{_bindir}/odidx %{_bindir}/qmttest %{_mandir}/man1/dpmgr.1.gz %{_mandir}/man1/dptest.1.gz %{_mandir}/man1/dptsv.1.gz %{_mandir}/man1/crmgr.1.gz %{_mandir}/man1/crtest.1.gz %{_mandir}/man1/crtsv.1.gz %{_mandir}/man1/rlmgr.1.gz %{_mandir}/man1/rltest.1.gz %{_mandir}/man1/hvmgr.1.gz %{_mandir}/man1/hvtest.1.gz %{_mandir}/man1/cbtest.1.gz %{_mandir}/man1/cbcodec.1.gz %{_mandir}/man1/vlmgr.1.gz %{_mandir}/man1/vltest.1.gz %{_mandir}/man1/vltsv.1.gz %{_mandir}/man1/odmgr.1.gz %{_mandir}/man1/odtest.1.gz %{_mandir}/man1/odidx.1.gz %{_mandir}/man1/qmttest.1.gz %{_mandir}/man3/qdbm.3.gz %{_mandir}/man3/depot.3.gz %{_mandir}/man3/dpopen.3.gz %{_mandir}/man3/curia.3.gz %{_mandir}/man3/cropen.3.gz %{_mandir}/man3/relic.3.gz %{_mandir}/man3/hovel.3.gz %{_mandir}/man3/cabin.3.gz %{_mandir}/man3/villa.3.gz %{_mandir}/man3/vlopen.3.gz %{_mandir}/man3/vista.3.gz %{_mandir}/man3/odeum.3.gz %{_mandir}/man3/odopen.3.gz %{_datadir}/doc/qdbm/spex.html %{_datadir}/doc/qdbm/spex-ja.html %{_datadir}/doc/qdbm/COPYING %{_datadir}/doc/qdbm/ChangeLog %{_datadir}/doc/qdbm/NEWS %{_datadir}/doc/qdbm/THANKS %{_libdir}/pkgconfig/qdbm.pc %files plus %defattr(-,root,root) %{_includedir}/xqdbm.h %{_includedir}/xadbm.h %{_includedir}/xdepot.h %{_includedir}/xcuria.h %{_includedir}/xvilla.h %{_libdir}/libxqdbm.a %{_libdir}/libxqdbm.so.3.0.0 %{_libdir}/libxqdbm.so.3 %{_libdir}/libxqdbm.so %{_bindir}/xdptest %{_bindir}/xcrtest %{_bindir}/xvltest %{_datadir}/doc/qdbm/xspex.html %{_datadir}/doc/qdbm/xspex-ja.html %{_datadir}/doc/qdbm/xapidoc/ %files java %defattr(-,root,root) %{_libdir}/qdbm.jar %{_libdir}/libjqdbm.so.1.0.0 %{_libdir}/libjqdbm.so.1 %{_libdir}/libjqdbm.so %{_datadir}/doc/qdbm/jspex.html %{_datadir}/doc/qdbm/jspex-ja.html %{_datadir}/doc/qdbm/japidoc/ %files cgi %defattr(-,root,root) %{_libexecdir}/qadm.cgi %{_libexecdir}/qupl.cgi %{_libexecdir}/qfts.cgi %{_datadir}/qdbm/cgi/qadm.conf %{_datadir}/qdbm/cgi/qupl.conf %{_datadir}/qdbm/cgi/qfts.conf %{_datadir}/doc/qdbm/cgispex.html %{_datadir}/doc/qdbm/cgispex-ja.html # END OF FILE qdbm-1.8.78/villa.h0000644000175000017500000011162610573416530013037 0ustar mikiomikio/************************************************************************************************* * The advanced API of QDBM * Copyright (C) 2000-2007 Mikio Hirabayashi * This file is part of QDBM, Quick Database Manager. * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU * Lesser General Public License as published by the Free Software Foundation; either version * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * You should have received a copy of the GNU Lesser General Public License along with QDBM; if * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. *************************************************************************************************/ #ifndef _VILLA_H /* duplication check */ #define _VILLA_H #if defined(__cplusplus) /* export for C++ */ extern "C" { #endif #include #include #include #include #if defined(_MSC_VER) && !defined(QDBM_INTERNAL) && !defined(QDBM_STATIC) #define MYEXTERN extern __declspec(dllimport) #else #define MYEXTERN extern #endif /************************************************************************************************* * API *************************************************************************************************/ #define VL_LEVELMAX 64 /* max level of B+ tree */ typedef struct { /* type of structure for a record */ CBDATUM *key; /* datum of the key */ CBDATUM *first; /* datum of the first value */ CBLIST *rest; /* list of the rest values */ } VLREC; typedef struct { /* type of structure for index of a page */ int pid; /* ID number of the referring page */ CBDATUM *key; /* threshold key of the page */ } VLIDX; typedef struct { /* type of structure for a leaf page */ int id; /* ID number of the leaf */ int dirty; /* whether to be written back */ CBLIST *recs; /* list of records */ int prev; /* ID number of the previous leaf */ int next; /* ID number of the next leaf */ } VLLEAF; typedef struct { /* type of structure for a node page */ int id; /* ID number of the node */ int dirty; /* whether to be written back */ int heir; /* ID of the child before the first index */ CBLIST *idxs; /* list of indexes */ } VLNODE; /* type of the pointer to a comparing function. `aptr' specifies the pointer to the region of one key. `asiz' specifies the size of the region of one key. `bptr' specifies the pointer to the region of the other key. `bsiz' specifies the size of the region of the other key. The return value is positive if the former is big, negative if the latter is big, 0 if both are equivalent. */ typedef int (*VLCFUNC)(const char *aptr, int asiz, const char *bptr, int bsiz); MYEXTERN VLCFUNC VL_CMPLEX; /* lexical comparing function */ MYEXTERN VLCFUNC VL_CMPINT; /* native integer comparing function */ MYEXTERN VLCFUNC VL_CMPNUM; /* big endian number comparing function */ MYEXTERN VLCFUNC VL_CMPDEC; /* decimal string comparing function */ typedef struct { /* type of structure for a database handle */ DEPOT *depot; /* internal database handle */ VLCFUNC cmp; /* pointer to the comparing function */ int wmode; /* whether to be writable */ int cmode; /* compression mode for leaves */ int root; /* ID number of the root page */ int last; /* ID number of the last leaf */ int lnum; /* number of leaves */ int nnum; /* number of nodes */ int rnum; /* number of records */ CBMAP *leafc; /* cache for leaves */ CBMAP *nodec; /* cache for nodes */ int hist[VL_LEVELMAX]; /* array history of visited nodes */ int hnum; /* number of elements of the history */ int hleaf; /* ID number of the leaf referred by the history */ int lleaf; /* ID number of the last visited leaf */ int curleaf; /* ID number of the leaf where the cursor is */ int curknum; /* index of the key where the cursor is */ int curvnum; /* index of the value where the cursor is */ int leafrecmax; /* max number of records in a leaf */ int nodeidxmax; /* max number of indexes in a node */ int leafcnum; /* max number of caching leaves */ int nodecnum; /* max number of caching nodes */ int avglsiz; /* average size of each leave */ int avgnsiz; /* average size of each node */ int tran; /* whether in the transaction */ int rbroot; /* root for rollback */ int rblast; /* last for rollback */ int rblnum; /* lnum for rollback */ int rbnnum; /* nnum for rollback */ int rbrnum; /* rnum for rollback */ } VILLA; typedef struct { /* type of structure for a multiple cursor handle */ VILLA *villa; /* database handle */ int curleaf; /* ID number of the leaf where the cursor is */ int curknum; /* index of the key where the cursor is */ int curvnum; /* index of the value where the cursor is */ } VLMULCUR; enum { /* enumeration for open modes */ VL_OREADER = 1 << 0, /* open as a reader */ VL_OWRITER = 1 << 1, /* open as a writer */ VL_OCREAT = 1 << 2, /* a writer creating */ VL_OTRUNC = 1 << 3, /* a writer truncating */ VL_ONOLCK = 1 << 4, /* open without locking */ VL_OLCKNB = 1 << 5, /* lock without blocking */ VL_OZCOMP = 1 << 6, /* compress leaves with ZLIB */ VL_OYCOMP = 1 << 7, /* compress leaves with LZO */ VL_OXCOMP = 1 << 8 /* compress leaves with BZIP2 */ }; enum { /* enumeration for write modes */ VL_DOVER, /* overwrite the existing value */ VL_DKEEP, /* keep the existing value */ VL_DCAT, /* concatenate values */ VL_DDUP, /* allow duplication of keys */ VL_DDUPR /* allow duplication with reverse order */ }; enum { /* enumeration for jump modes */ VL_JFORWARD, /* step forward */ VL_JBACKWARD /* step backward */ }; enum { /* enumeration for insertion modes */ VL_CPCURRENT, /* overwrite the current record */ VL_CPBEFORE, /* insert before the current record */ VL_CPAFTER /* insert after the current record */ }; /* Get a database handle. `name' specifies the name of a database file. `omode' specifies the connection mode: `VL_OWRITER' as a writer, `VL_OREADER' as a reader. If the mode is `VL_OWRITER', the following may be added by bitwise or: `VL_OCREAT', which means it creates a new database if not exist, `VL_OTRUNC', which means it creates a new database regardless if one exists, `VL_OZCOMP', which means leaves in the database are compressed with ZLIB, `VL_OYCOMP', which means leaves in the database are compressed with LZO, `VL_OXCOMP', which means leaves in the database are compressed with BZIP2. Both of `VL_OREADER' and `VL_OWRITER' can be added to by bitwise or: `VL_ONOLCK', which means it opens a database file without file locking, or `VL_OLCKNB', which means locking is performed without blocking. `cmp' specifies a comparing function: `VL_CMPLEX' comparing keys in lexical order, `VL_CMPINT' comparing keys as objects of `int' in native byte order, `VL_CMPNUM' comparing keys as numbers of big endian, `VL_CMPDEC' comparing keys as decimal strings. Any function based on the declaration of the type `VLCFUNC' can be assigned to the comparing function. The comparing function should be kept same in the life of a database. The return value is the database handle or `NULL' if it is not successful. While connecting as a writer, an exclusive lock is invoked to the database file. While connecting as a reader, a shared lock is invoked to the database file. The thread blocks until the lock is achieved. `VL_OZCOMP', `VL_OYCOMP', and `VL_OXCOMP' are available only if QDBM was built each with ZLIB, LZO, and BZIP2 enabled. If `VL_ONOLCK' is used, the application is responsible for exclusion control. */ VILLA *vlopen(const char *name, int omode, VLCFUNC cmp); /* Close a database handle. `villa' specifies a database handle. If successful, the return value is true, else, it is false. Because the region of a closed handle is released, it becomes impossible to use the handle. Updating a database is assured to be written when the handle is closed. If a writer opens a database but does not close it appropriately, the database will be broken. If the transaction is activated and not committed, it is aborted. */ int vlclose(VILLA *villa); /* Store a record. `villa' specifies a database handle connected as a writer. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `vbuf' specifies the pointer to the region of a value. `vsiz' specifies the size of the region of the value. If it is negative, the size is assigned with `strlen(vbuf)'. `dmode' specifies behavior when the key overlaps, by the following values: `VL_DOVER', which means the specified value overwrites the existing one, `VL_DKEEP', which means the existing value is kept, `VL_DCAT', which means the specified value is concatenated at the end of the existing value, `VL_DDUP', which means duplication of keys is allowed and the specified value is added as the last one, `VL_DDUPR', which means duplication of keys is allowed and the specified value is added as the first one. If successful, the return value is true, else, it is false. The cursor becomes unavailable due to updating database. */ int vlput(VILLA *villa, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int dmode); /* Delete a record. `villa' specifies a database handle connected as a writer. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. If successful, the return value is true, else, it is false. False is returned when no record corresponds to the specified key. When the key of duplicated records is specified, the first record of the same key is deleted. The cursor becomes unavailable due to updating database. */ int vlout(VILLA *villa, const char *kbuf, int ksiz); /* Retrieve a record. `villa' specifies a database handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the region of the value of the corresponding record, else, it is `NULL'. `NULL' is returned when no record corresponds to the specified key. When the key of duplicated records is specified, the value of the first record of the same key is selected. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. */ char *vlget(VILLA *villa, const char *kbuf, int ksiz, int *sp); /* Get the size of the value of a record. `villa' specifies a database handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. If successful, the return value is the size of the value of the corresponding record, else, it is -1. If multiple records correspond, the size of the first is returned. */ int vlvsiz(VILLA *villa, const char *kbuf, int ksiz); /* Get the number of records corresponding a key. `villa' specifies a database handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. The return value is the number of corresponding records. If no record corresponds, 0 is returned. */ int vlvnum(VILLA *villa, const char *kbuf, int ksiz); /* Store plural records corresponding a key. `villa' specifies a database handle connected as a writer. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `vals' specifies a list handle of values. The list should not be empty. If successful, the return value is true, else, it is false. The cursor becomes unavailable due to updating database. */ int vlputlist(VILLA *villa, const char *kbuf, int ksiz, const CBLIST *vals); /* Delete all records corresponding a key. `villa' specifies a database handle connected as a writer. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. If successful, the return value is true, else, it is false. False is returned when no record corresponds to the specified key. The cursor becomes unavailable due to updating database. */ int vloutlist(VILLA *villa, const char *kbuf, int ksiz); /* Retrieve values of all records corresponding a key. `villa' specifies a database handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. If successful, the return value is a list handle of the values of the corresponding records, else, it is `NULL'. `NULL' is returned when no record corresponds to the specified key. Because the handle of the return value is opened with the function `cblistopen', it should be closed with the function `cblistclose' if it is no longer in use. */ CBLIST *vlgetlist(VILLA *villa, const char *kbuf, int ksiz); /* Retrieve concatenated values of all records corresponding a key. `villa' specifies a database handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the region of the concatenated values of the corresponding record, else, it is `NULL'. `NULL' is returned when no record corresponds to the specified key. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. */ char *vlgetcat(VILLA *villa, const char *kbuf, int ksiz, int *sp); /* Move the cursor to the first record. `villa' specifies a database handle. If successful, the return value is true, else, it is false. False is returned if there is no record in the database. */ int vlcurfirst(VILLA *villa); /* Move the cursor to the last record. `villa' specifies a database handle. If successful, the return value is true, else, it is false. False is returned if there is no record in the database. */ int vlcurlast(VILLA *villa); /* Move the cursor to the previous record. `villa' specifies a database handle. If successful, the return value is true, else, it is false. False is returned if there is no previous record. */ int vlcurprev(VILLA *villa); /* Move the cursor to the next record. `villa' specifies a database handle. If successful, the return value is true, else, it is false. False is returned if there is no next record. */ int vlcurnext(VILLA *villa); /* Move the cursor to a position around a record. `villa' specifies a database handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `jmode' specifies detail adjustment: `VL_JFORWARD', which means that the cursor is set to the first record of the same key and that the cursor is set to the next substitute if completely matching record does not exist, `VL_JBACKWARD', which means that the cursor is set to the last record of the same key and that the cursor is set to the previous substitute if completely matching record does not exist. If successful, the return value is true, else, it is false. False is returned if there is no record corresponding the condition. */ int vlcurjump(VILLA *villa, const char *kbuf, int ksiz, int jmode); /* Get the key of the record where the cursor is. `villa' specifies a database handle. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the region of the key of the corresponding record, else, it is `NULL'. `NULL' is returned when no record corresponds to the cursor. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. */ char *vlcurkey(VILLA *villa, int *sp); /* Get the value of the record where the cursor is. `villa' specifies a database handle. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the region of the value of the corresponding record, else, it is `NULL'. `NULL' is returned when no record corresponds to the cursor. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. */ char *vlcurval(VILLA *villa, int *sp); /* Insert a record around the cursor. `villa' specifies a database handle connected as a writer. `vbuf' specifies the pointer to the region of a value. `vsiz' specifies the size of the region of the value. If it is negative, the size is assigned with `strlen(vbuf)'. `cpmode' specifies detail adjustment: `VL_CPCURRENT', which means that the value of the current record is overwritten, `VL_CPBEFORE', which means that a new record is inserted before the current record, `VL_CPAFTER', which means that a new record is inserted after the current record. If successful, the return value is true, else, it is false. False is returned when no record corresponds to the cursor. After insertion, the cursor is moved to the inserted record. */ int vlcurput(VILLA *villa, const char *vbuf, int vsiz, int cpmode); /* Delete the record where the cursor is. `villa' specifies a database handle connected as a writer. If successful, the return value is true, else, it is false. False is returned when no record corresponds to the cursor. After deletion, the cursor is moved to the next record if possible. */ int vlcurout(VILLA *villa); /* Set the tuning parameters for performance. `villa' specifies a database handle. `lrecmax' specifies the max number of records in a leaf node of B+ tree. If it is not more than 0, the default value is specified. `nidxmax' specifies the max number of indexes in a non-leaf node of B+ tree. If it is not more than 0, the default value is specified. `lcnum' specifies the max number of caching leaf nodes. If it is not more than 0, the default value is specified. `ncnum' specifies the max number of caching non-leaf nodes. If it is not more than 0, the default value is specified. The default setting is equivalent to `vlsettuning(49, 192, 1024, 512)'. Because tuning parameters are not saved in a database, you should specify them every opening a database. */ void vlsettuning(VILLA *villa, int lrecmax, int nidxmax, int lcnum, int ncnum); /* Set the size of the free block pool of a database handle. `villa' specifies a database handle connected as a writer. `size' specifies the size of the free block pool of a database. If successful, the return value is true, else, it is false. The default size of the free block pool is 256. If the size is greater, the space efficiency of overwriting values is improved with the time efficiency sacrificed. */ int vlsetfbpsiz(VILLA *villa, int size); /* Synchronize updating contents with the file and the device. `villa' specifies a database handle connected as a writer. If successful, the return value is true, else, it is false. This function is useful when another process uses the connected database file. This function should not be used while the transaction is activated. */ int vlsync(VILLA *villa); /* Optimize a database. `villa' specifies a database handle connected as a writer. If successful, the return value is true, else, it is false. In an alternating succession of deleting and storing with overwrite or concatenate, dispensable regions accumulate. This function is useful to do away with them. This function should not be used while the transaction is activated. */ int vloptimize(VILLA *villa); /* Get the name of a database. `villa' specifies a database handle. If successful, the return value is the pointer to the region of the name of the database, else, it is `NULL'. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. */ char *vlname(VILLA *villa); /* Get the size of a database file. `villa' specifies a database handle. If successful, the return value is the size of the database file, else, it is -1. Because of the I/O buffer, the return value may be less than the hard size. */ int vlfsiz(VILLA *villa); /* Get the number of the leaf nodes of B+ tree. `villa' specifies a database handle. If successful, the return value is the number of the leaf nodes, else, it is -1. */ int vllnum(VILLA *villa); /* Get the number of the non-leaf nodes of B+ tree. `villa' specifies a database handle. If successful, the return value is the number of the non-leaf nodes, else, it is -1. */ int vlnnum(VILLA *villa); /* Get the number of the records stored in a database. `villa' specifies a database handle. If successful, the return value is the number of the records stored in the database, else, it is -1. */ int vlrnum(VILLA *villa); /* Check whether a database handle is a writer or not. `villa' specifies a database handle. The return value is true if the handle is a writer, false if not. */ int vlwritable(VILLA *villa); /* Check whether a database has a fatal error or not. `villa' specifies a database handle. The return value is true if the database has a fatal error, false if not. */ int vlfatalerror(VILLA *villa); /* Get the inode number of a database file. `villa' specifies a database handle. The return value is the inode number of the database file. */ int vlinode(VILLA *villa); /* Get the last modified time of a database. `villa' specifies a database handle. The return value is the last modified time of the database. */ time_t vlmtime(VILLA *villa); /* Begin the transaction. `villa' specifies a database handle connected as a writer. If successful, the return value is true, else, it is false. Because this function does not perform mutual exclusion control in multi-thread, the application is responsible for it. Only one transaction can be activated with a database handle at the same time. */ int vltranbegin(VILLA *villa); /* Commit the transaction. `villa' specifies a database handle connected as a writer. If successful, the return value is true, else, it is false. Updating a database in the transaction is fixed when it is committed successfully. */ int vltrancommit(VILLA *villa); /* Abort the transaction. `villa' specifies a database handle connected as a writer. If successful, the return value is true, else, it is false. Updating a database in the transaction is discarded when it is aborted. The state of the database is rollbacked to before transaction. */ int vltranabort(VILLA *villa); /* Remove a database file. `name' specifies the name of a database file. If successful, the return value is true, else, it is false. */ int vlremove(const char *name); /* Repair a broken database file. `name' specifies the name of a database file. `cmp' specifies the comparing function of the database file. If successful, the return value is true, else, it is false. There is no guarantee that all records in a repaired database file correspond to the original or expected state. */ int vlrepair(const char *name, VLCFUNC cmp); /* Dump all records as endian independent data. `villa' specifies a database handle. `name' specifies the name of an output file. If successful, the return value is true, else, it is false. */ int vlexportdb(VILLA *villa, const char *name); /* Load all records from endian independent data. `villa' specifies a database handle connected as a writer. The database of the handle must be empty. `name' specifies the name of an input file. If successful, the return value is true, else, it is false. */ int vlimportdb(VILLA *villa, const char *name); /************************************************************************************************* * features for experts *************************************************************************************************/ /* Number of division of the database for Vista. */ #define vlcrdnum (*vlcrdnumptr()) /* Get the pointer of the variable of the number of division of the database for Vista. The return value is the pointer of the variable. */ int *vlcrdnumptr(void); /* Synchronize updating contents on memory. `villa' specifies a database handle connected as a writer. If successful, the return value is true, else, it is false. */ int vlmemsync(VILLA *villa); /* Synchronize updating contents on memory, not physically. `villa' specifies a database handle connected as a writer. If successful, the return value is true, else, it is false. */ int vlmemflush(VILLA *villa); /* Refer to volatile cache of a value of a record. `villa' specifies a database handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the region of the value of the corresponding record, else, it is `NULL'. `NULL' is returned when no record corresponds to the specified key. Because the region of the return value is volatile and it may be spoiled by another operation of the database, the data should be copied into another involatile buffer immediately. */ const char *vlgetcache(VILLA *villa, const char *kbuf, int ksiz, int *sp); /* Refer to volatile cache of the key of the record where the cursor is. `villa' specifies a database handle. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the region of the key of the corresponding record, else, it is `NULL'. `NULL' is returned when no record corresponds to the cursor. Because the region of the return value is volatile and it may be spoiled by another operation of the database, the data should be copied into another involatile buffer immediately. */ const char *vlcurkeycache(VILLA *villa, int *sp); /* Refer to volatile cache of the value of the record where the cursor is. `villa' specifies a database handle. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the region of the value of the corresponding record, else, it is `NULL'. `NULL' is returned when no record corresponds to the cursor. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. */ const char *vlcurvalcache(VILLA *villa, int *sp); /* Get a multiple cursor handle. `villa' specifies a database handle connected as a reader. The return value is a multiple cursor handle or `NULL' if it is not successful. The returned object is should be closed before the database handle is closed. Even if plural cursors are fetched out of a database handle, they does not share the locations with each other. Note that this function can be used only if the database handle is connected as a reader. */ VLMULCUR *vlmulcuropen(VILLA *villa); /* Close a multiple cursor handle. `mulcur' specifies a multiple cursor handle. */ void vlmulcurclose(VLMULCUR *mulcur); /* Move a multiple cursor to the first record. `mulcur' specifies a multiple cursor handle. If successful, the return value is true, else, it is false. False is returned if there is no record in the database. */ int vlmulcurfirst(VLMULCUR *mulcur); /* Move a multiple cursor to the last record. `mulcur' specifies a multiple cursor handle. If successful, the return value is true, else, it is false. False is returned if there is no record in the database. */ int vlmulcurlast(VLMULCUR *mulcur); /* Move a multiple cursor to the previous record. `mulcur' specifies a multiple cursor handle. If successful, the return value is true, else, it is false. False is returned if there is no previous record. */ int vlmulcurprev(VLMULCUR *mulcur); /* Move a multiple cursor to the next record. `mulcur' specifies a multiple cursor handle. If successful, the return value is true, else, it is false. False is returned if there is no next record. */ int vlmulcurnext(VLMULCUR *mulcur); /* Move a multiple cursor to a position around a record. `mulcur' specifies a multiple cursor handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `jmode' specifies detail adjustment: `VL_JFORWARD', which means that the cursor is set to the first record of the same key and that the cursor is set to the next substitute if completely matching record does not exist, `VL_JBACKWARD', which means that the cursor is set to the last record of the same key and that the cursor is set to the previous substitute if completely matching record does not exist. If successful, the return value is true, else, it is false. False is returned if there is no record corresponding the condition. */ int vlmulcurjump(VLMULCUR *mulcur, const char *kbuf, int ksiz, int jmode); /* Get the key of the record where a multiple cursor is. `mulcur' specifies a multiple cursor handle. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the region of the key of the corresponding record, else, it is `NULL'. `NULL' is returned when no record corresponds to the cursor. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. */ char *vlmulcurkey(VLMULCUR *mulcur, int *sp); /* Get the value of the record where a multiple cursor is. `mulcur' specifies a multiple cursor handle. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the region of the value of the corresponding record, else, it is `NULL'. `NULL' is returned when no record corresponds to the cursor. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. */ char *vlmulcurval(VLMULCUR *mulcur, int *sp); /* Refer to volatile cache of the key of the record where a multiple cursor is. `mulcur' specifies a multiple cursor handle. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the region of the key of the corresponding record, else, it is `NULL'. `NULL' is returned when no record corresponds to the cursor. Because the region of the return value is volatile and it may be spoiled by another operation of the database, the data should be copied into another involatile buffer immediately. */ const char *vlmulcurkeycache(VLMULCUR *mulcur, int *sp); /* Refer to volatile cache of the value of the record where a multiple cursor is. `mulcur' specifies a multiple cursor handle. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the region of the value of the corresponding record, else, it is `NULL'. `NULL' is returned when no record corresponds to the cursor. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. */ const char *vlmulcurvalcache(VLMULCUR *mulcur, int *sp); /* Get flags of a database. `villa' specifies a database handle. The return value is the flags of a database. */ int vlgetflags(VILLA *villa); /* Set flags of a database. `villa' specifies a database handle connected as a writer. `flags' specifies flags to set. Least ten bits are reserved for internal use. If successful, the return value is true, else, it is false. */ int vlsetflags(VILLA *villa, int flags); #undef MYEXTERN #if defined(__cplusplus) /* export for C++ */ } #endif #endif /* duplication check */ /* END OF FILE */ qdbm-1.8.78/doc/0000755000175000017500000000000011426315676012324 5ustar mikiomikioqdbm-1.8.78/doc/index.ja.html~0000644000175000017500000002054511426313572015107 0ustar mikiomikio データベースライブラリ QDBM

QDBM: Quick Database Manager

Copyright (C) 2000-2007 Mikio Hirabayashi
Last Update: Thu, 26 Oct 2006 15:00:20 +0900

概è¦

QDBMã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’扱ã†ãƒ«ãƒ¼ãƒãƒ³ç¾¤ã®ãƒ©ã‚¤ãƒ–ラリã§ã™ã€‚データベースã¨ã„ã£ã¦ã‚‚å˜ç´”ãªã‚‚ã®ã§ã€ã‚­ãƒ¼ã¨å€¤ã®ãƒšã‚¢ã‹ã‚‰ãªã‚‹ãƒ¬ã‚³ãƒ¼ãƒ‰ç¾¤ã‚’æ ¼ç´ã—ãŸãƒ‡ãƒ¼ã‚¿ãƒ•ァイルã§ã™ã€‚キーã¨å€¤ã¯ä»»æ„ã®é•·ã•ã‚’æŒã¤ä¸€é€£ã®ãƒã‚¤ãƒˆåˆ—ã§ã‚ã‚Šã€æ–‡å­—列ã§ã‚‚ãƒã‚¤ãƒŠãƒªã§ã‚‚扱ã†ã“ã¨ãŒã§ãã¾ã™ã€‚ãƒ†ãƒ¼ãƒ–ãƒ«ã‚„ãƒ‡ãƒ¼ã‚¿åž‹ã®æ¦‚念ã¯ã‚りã¾ã›ã‚“。レコードã¯ãƒãƒƒã‚·ãƒ¥è¡¨ã¾ãŸã¯B+木ã§ç·¨æˆã•れã¾ã™ã€‚

ãƒãƒƒã‚·ãƒ¥è¡¨ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã§ã¯ã€ã‚­ãƒ¼ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹å†…ã§ä¸€æ„ã§ã‚りã€ã‚­ãƒ¼ãŒé‡è¤‡ã™ã‚‹è¤‡æ•°ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’æ ¼ç´ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。ã“ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«å¯¾ã—ã¦ã¯ã€ã‚­ãƒ¼ã¨å€¤ã‚’指定ã—ã¦ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’æ ¼ç´ã—ãŸã‚Šã€ã‚­ãƒ¼ã‚’指定ã—ã¦å¯¾å¿œã™ã‚‹ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’削除ã—ãŸã‚Šã€ã‚­ãƒ¼ã‚’指定ã—ã¦å¯¾å¿œã™ã‚‹ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’検索ã—ãŸã‚Šã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ã¾ãŸã€ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«æ ¼ç´ã—ã¦ã‚ã‚‹å…¨ã¦ã®ã‚­ãƒ¼ã‚’é †ä¸åŒã«ä¸€ã¤ãšã¤å–り出ã™ã“ã¨ã‚‚ã§ãã¾ã™ã€‚ã“ã®ã‚ˆã†ãªæ“作ã¯ã€UNIX標準ã§å®šç¾©ã•れã¦ã„ã‚‹DBMライブラリãŠã‚ˆã³ãã®è¿½å¾“ã§ã‚ã‚‹NDBMã‚„GDBMã«é¡žã™ã‚‹ã‚‚ã®ã§ã™ã€‚QDBMã¯DBMã®ã‚ˆã‚Šè‰¯ã„代替ã¨ã—ã¦åˆ©ç”¨ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚

B+木ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã§ã¯ã€ã‚­ãƒ¼ãŒé‡è¤‡ã™ã‚‹è¤‡æ•°ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’æ ¼ç´ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ã“ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«å¯¾ã—ã¦ã¯ã€ãƒãƒƒã‚·ãƒ¥è¡¨ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã¨åŒæ§˜ã«ã€ã‚­ãƒ¼ã‚’指定ã—ã¦ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’æ ¼ç´ã—ãŸã‚Šå–り出ã—ãŸã‚Šå‰Šé™¤ã—ãŸã‚Šã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚レコードã¯ãƒ¦ãƒ¼ã‚¶ãŒæŒ‡ç¤ºã—ãŸæ¯”較関数ã«åŸºã¥ã„ã¦æ•´åˆ—ã•ã‚Œã¦æ ¼ç´ã•れã¾ã™ã€‚カーソルを用ã„ã¦å„レコードを昇順ã¾ãŸã¯é™é †ã§å‚ç…§ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ã“ã®æ©Ÿæ§‹ã«ã‚ˆã£ã¦ã€æ–‡å­—列ã®å‰æ–¹ä¸€è‡´æ¤œç´¢ã‚„数値ã®ç¯„囲検索ãŒå¯èƒ½ã«ãªã‚Šã¾ã™ã€‚ã¾ãŸã€B+木ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã§ã¯ãƒˆãƒ©ãƒ³ã‚¶ã‚¯ã‚·ãƒ§ãƒ³ãŒåˆ©ç”¨ã§ãã¾ã™ã€‚

QDBMã¯Cã§è¨˜è¿°ã•れã€Cã€C++ã€Javaã€PerlãŠã‚ˆã³Rubyã®APIã¨ã—ã¦æä¾›ã•れã¾ã™ã€‚QDBMã¯POSIX準拠ã®APIã‚’å‚™ãˆã‚‹ãƒ—ラットフォームã§åˆ©ç”¨ã§ãã¾ã™ã€‚QDBMã¯GNU Lesser General Public Licenseã«åŸºã¥ãフリーソフトウェアã§ã™ã€‚


文書

ä»¥ä¸‹ã®æ–‡æ›¸ã‚’ãŠèª­ã¿ãã ã•ã„。ソースパッケージã«ã‚‚åŒã˜ã‚‚ã®ãŒå«ã¾ã‚Œã¦ã„ã¾ã™ã€‚


ダウンロード

以下ã®ãƒ‘ッケージをダウンロードã—ã¦ãã ã•ã„。Linux用ãƒã‚¤ãƒŠãƒªãƒ‘ッケージã¯ã€Cã¨C++ã¨Javaã®APIã¨ã€CGIスクリプトをç´ã‚ã¦ã„ã¾ã™ã€‚Windows用ãƒã‚¤ãƒŠãƒªãƒ‘ッケージã¯ã€Cã¨Javaã®APIã¨ã€CGIスクリプトをç´ã‚ã¦ã„ã¾ã™ã€‚


ãã®ä»–ã®æƒ…å ±

QDBMã¯å¹³æž—幹雄ãŒä½œæˆã—ã¾ã—ãŸã€‚作者ã¨é€£çµ¡ã‚’ã¨ã‚‹ã«ã¯ã€`mikio@fallabs.com' å®›ã«é›»å­ãƒ¡ãƒ¼ãƒ«ã‚’é€ã£ã¦ãã ã•ã„。


qdbm-1.8.78/doc/index.html0000644000175000017500000001542411426315665014325 0ustar mikiomikio QDBM: Quick Database Manager

QDBM: Quick Database Manager

Copyright (C) 2000-2007 Mikio Hirabayashi
Last Update: Thu, 26 Oct 2006 15:00:20 +0900

Overview

QDBM is a library of routines for managing a database. The database is a simple data file containing records, each is a pair of a key and a value. Every key and value is serial bytes with variable length. Both binary data and character string can be used as a key and a value. There is neither concept of data tables nor data types. Records are organized in hash table or B+ tree.

As for database of hash table, each key must be unique within a database, so it is impossible to store two or more records with a key overlaps. The following access methods are provided to the database: storing a record with a key and a value, deleting a record by a key, retrieving a record by a key. Moreover, traversal access to every key are provided, although the order is arbitrary. These access methods are similar to ones of DBM (or its followers: NDBM and GDBM) library defined in the UNIX standard. QDBM is an alternative for DBM because of its higher performance.

As for database of B+ tree, records whose keys are duplicated can be stored. Access methods of storing, deleting, and retrieving are provided as with the database of hash table. Records are stored in order by a comparing function assigned by a user. It is possible to access each record with the cursor in ascending or descending order. According to this mechanism, forward matching search for strings and range search for integers are realized. Moreover, transaction is available in database of B+ tree.

QDBM is written in C, and provided as APIs of C, C++, Java, Perl, and Ruby. QDBM is available on platforms which have API conforming to POSIX. QDBM is a free software licensed under the GNU Lesser General Public License.


Documents

The following are documents of QDBM. They are contained also in the source package.


Packages

The following are packages of QDBM. The Linux binary package contains APIs for C, C++, and Java. It contains CGI scripts also. The Windows binary package contains APIs for C and Java. It contains CGI scripts also.


Information

QDBM was written by Mikio Hirabayashi. You can contact the author by e-mail to `mikio@fallabs.com'.


qdbm-1.8.78/doc/index.html~0000644000175000017500000001542411426313554014516 0ustar mikiomikio QDBM: Quick Database Manager

QDBM: Quick Database Manager

Copyright (C) 2000-2007 Mikio Hirabayashi
Last Update: Thu, 26 Oct 2006 15:00:20 +0900

Overview

QDBM is a library of routines for managing a database. The database is a simple data file containing records, each is a pair of a key and a value. Every key and value is serial bytes with variable length. Both binary data and character string can be used as a key and a value. There is neither concept of data tables nor data types. Records are organized in hash table or B+ tree.

As for database of hash table, each key must be unique within a database, so it is impossible to store two or more records with a key overlaps. The following access methods are provided to the database: storing a record with a key and a value, deleting a record by a key, retrieving a record by a key. Moreover, traversal access to every key are provided, although the order is arbitrary. These access methods are similar to ones of DBM (or its followers: NDBM and GDBM) library defined in the UNIX standard. QDBM is an alternative for DBM because of its higher performance.

As for database of B+ tree, records whose keys are duplicated can be stored. Access methods of storing, deleting, and retrieving are provided as with the database of hash table. Records are stored in order by a comparing function assigned by a user. It is possible to access each record with the cursor in ascending or descending order. According to this mechanism, forward matching search for strings and range search for integers are realized. Moreover, transaction is available in database of B+ tree.

QDBM is written in C, and provided as APIs of C, C++, Java, Perl, and Ruby. QDBM is available on platforms which have API conforming to POSIX. QDBM is a free software licensed under the GNU Lesser General Public License.


Documents

The following are documents of QDBM. They are contained also in the source package.


Packages

The following are packages of QDBM. The Linux binary package contains APIs for C, C++, and Java. It contains CGI scripts also. The Windows binary package contains APIs for C and Java. It contains CGI scripts also.


Information

QDBM was written by Mikio Hirabayashi. You can contact the author by e-mail to `mikio@fallabs.com'.


qdbm-1.8.78/doc/spex.html0000644000175000017500000107102111426310326014156 0ustar mikiomikio Specifications of QDBM Version 1

Fundamental Specifications of QDBM Version 1

Copyright (C) 2000-2007 Mikio Hirabayashi
Last Update: Thu, 26 Oct 2006 15:00:20 +0900

Table of Contents

  1. Overview
  2. Features
  3. Installation
  4. Depot: Basic API
  5. Commands for Depot
  6. Curia: Extended API
  7. Commands for Curia
  8. Relic: NDBM-compatible API
  9. Commands for Relic
  10. Hovel: GDBM-compatible API
  11. Commands for Hovel
  12. Cabin: Utility API
  13. Commands for Cabin
  14. Villa: Advanced API
  15. Commands for Villa
  16. Odeum: Inverted API
  17. Commands for Odeum
  18. File Format
  19. Porting
  20. Bugs
  21. Frequently Asked Questions
  22. Copying

Overview

QDBM is a library of routines for managing a database. The database is a simple data file containing records, each is a pair of a key and a value. Every key and value is serial bytes with variable length. Both binary data and character string can be used as a key and a value. There is neither concept of data tables nor data types. Records are organized in hash table or B+ tree.

As for database of hash table, each key must be unique within a database, so it is impossible to store two or more records with a key overlaps. The following access methods are provided to the database: storing a record with a key and a value, deleting a record by a key, retrieving a record by a key. Moreover, traversal access to every key are provided, although the order is arbitrary. These access methods are similar to ones of DBM (or its followers: NDBM and GDBM) library defined in the UNIX standard. QDBM is an alternative for DBM because of its higher performance.

As for database of B+ tree, records whose keys are duplicated can be stored. Access methods of storing, deleting, and retrieving are provided as with the database of hash table. Records are stored in order by a comparing function assigned by a user. It is possible to access each record with the cursor in ascending or descending order. According to this mechanism, forward matching search for strings and range search for integers are realized. Moreover, transaction is available in database of B+ tree.

QDBM is written in C, and provided as APIs of C, C++, Java, Perl, and Ruby. QDBM is available on platforms which have API conforming to POSIX. QDBM is a free software licensed under the GNU Lesser General Public License.


Features

Effective Implementation of Hash Database

QDBM is developed referring to GDBM for the purpose of the following three points: higher processing speed, smaller size of a database file, and simpler API. They have been achieved. Moreover, as with GDBM, the following three restrictions of traditional DBM: a process can handle only one database, the size of a key and a value is bounded, a database file is sparse, are cleared.

QDBM uses hash algorithm to retrieve records. If a bucket array has sufficient number of elements, the time complexity of retrieval is `O(1)'. That is, time required for retrieving a record is constant, regardless of the scale of a database. It is also the same about storing and deleting. Collision of hash values is managed by separate chaining. Data structure of the chains is binary search tree. Even if a bucket array has unusually scarce elements, the time complexity of retrieval is `O(log n)'.

QDBM attains improvement in retrieval by loading RAM with the whole of a bucket array. If a bucket array is on RAM, it is possible to access a region of a target record by about one path of file operations. A bucket array saved in a file is not read into RAM with the `read' call but directly mapped to RAM with the `mmap' call. Therefore, preparation time on connecting to a database is very short, and two or more processes can share the same memory map.

If the number of elements of a bucket array is about half of records stored within a database, although it depends on characteristic of the input, the probability of collision of hash values is about 56.7% (36.8% if the same, 21.3% if twice, 11.5% if four times, 6.0% if eight times). In such case, it is possible to retrieve a record by two or less paths of file operations. If it is made into a performance index, in order to handle a database containing one million of records, a bucket array with half a million of elements is needed. The size of each element is 4 bytes. That is, if 2M bytes of RAM is available, a database containing one million records can be handled.

QDBM provides two modes to connect to a database: `reader' and `writer'. A reader can perform retrieving but neither storing nor deleting. A writer can perform all access methods. Exclusion control between processes is performed when connecting to a database by file locking. While a writer is connected to a database, neither readers nor writers can be connected. While a reader is connected to a database, other readers can be connect, but writers can not. According to this mechanism, data consistency is guaranteed with simultaneous connections in multitasking environment.

Traditional DBM provides two modes of the storing operations: `insert' and `replace'. In the case a key overlaps an existing record, the insert mode keeps the existing value, while the replace mode transposes it to the specified value. In addition to the two modes, QDBM provides `concatenate' mode. In the mode, the specified value is concatenated at the end of the existing value and stored. This feature is useful when adding a element to a value as an array. Moreover, although DBM has a method to fetch out a value from a database only by reading the whole of a region of a record, QDBM has a method to fetch out a part of a region of a value. When a value is treated as an array, this feature is also useful.

Generally speaking, while succession of updating, fragmentation of available regions occurs, and the size of a database grows rapidly. QDBM deal with this problem by coalescence of dispensable regions and reuse of them, and featuring of optimization of a database. When overwriting a record with a value whose size is greater than the existing one, it is necessary to remove the region to another position of the file. Because the time complexity of the operation depends on the size of the region of a record, extending values successively is inefficient. However, QDBM deal with this problem by alignment. If increment can be put in padding, it is not necessary to remove the region.

As for many file systems, it is impossible to handle a file whose size is more than 2GB. To deal with this problem, QDBM provides a directory database containing multiple database files. Due to this feature, it is possible to handle a database whose total size is up to 1TB in theory. Moreover, because database files can be deployed on multiple disks, the speed of updating operations can be improved as with RAID-0 (striping). It is also possible for the database files to deploy on multiple file servers using NFS and so on.

Useful Implementation of B+ Tree Database

Although B+ tree database is slower than hash database, it features ordering access to each record. The order can be assigned by users. Records of B+ tree are sorted and arranged in logical pages. Sparse index organized in B tree that is multiway balanced tree are maintained for each page. Thus, the time complexity of retrieval and so on is `O(log n)'. Cursor is provided to access each record in order. The cursor can jump to a position specified by a key and can step forward or backward from the current position. Because each page is arranged as double linked list, the time complexity of stepping cursor is `O(1)'.

B+ tree database is implemented, based on above hash database. Because each page of B+ tree is stored as each record of hash database, B+ tree database inherits efficiency of storage management of hash database. Because the header of each record is smaller and alignment of each page is adjusted according to the page size, in most cases, the size of database file is cut by half compared to one of hash database. Although operation of many pages are required to update B+ tree, QDBM expedites the process by caching pages and reducing file operations. In most cases, because whole of the sparse index is cached on memory, it is possible to retrieve a record by one or less path of file operations.

B+ tree database features transaction mechanism. It is possible to commit a series of operations between the beginning and the end of the transaction in a lump, or to abort the transaction and perform rollback to the state before the transaction. Even if the process of an application is crashed while the transaction, the database file is not broken.

In case that QDBM was built with ZLIB, LZO, or BZIP2 enabled, a lossless data-compression library, the content of each page of B+ tree is compressed and stored in a file. Because each record in a page has similar patterns, high efficiency of compression is expected due to the Lempel-Ziv algorithm and the like. In case handling text data, the size of a database is reduced to about 25%. If the scale of a database is large and disk I/O is the bottleneck, featuring compression makes the processing speed improved to a large extent.

Simple but Various Interfaces

QDBM provides very simple APIs. You can perform database I/O as usual file I/O with `FILE' pointer defined in ANSI C. In the basic API of QDBM, entity of a database is recorded as one file. In the extended API, entity of a database is recorded as several files in one directory. Because the two APIs are very similar with each other, porting an application from one to the other is easy.

APIs which are compatible with NDBM and GDBM are also provided. As there are a lot of applications using NDBM or GDBM, it is easy to port them onto QDBM. In most cases, it is completed only by replacement of header including (#include) and re-compiling. However, QDBM can not handle database files made by the original NDBM or GDBM.

In order to handle records on memory easily, the utility API is provided. It implements memory allocating functions, sorting functions, extensible datum, array list, hash map, and so on. Using them, you can handle records in C language cheaply as in such script languages as Perl or Ruby.

B+ tree database is used with the advanced API. The advanced API is implemented using the basic API and the utility API. Because the advanced API is also similar to the basic API and the extended API, it is easy to learn how to use it.

In order to handle an inverted index which is used by full-text search systems, the inverted API is provided. If it is easy to handle an inverted index of documents, an application can focus on text processing and natural language processing. Because this API does not depend on character codes nor languages, it is possible to implement a full-text search system which can respond to various requests from users.

Along with APIs for C, QDBM provides APIs for C++, Java, Perl, and Ruby. APIs for C are composed of seven kinds: the basic API, the extended API, the NDBM-compatible API, the GDBM-compatible API, the utility API, the advanced API, and the inverted API. Command line interfaces corresponding to each API are also provided. They are useful for prototyping, testing, debugging, and so on. The C++ API encapsulates database handling functions of the basic API, the extended API, and the advanced API with class mechanism of C++. The Java API has native methods calling the basic API, the extended API, and the advanced API with Java Native Interface. The Perl API has methods calling the basic API, the extended API, and the advanced API with XS language. The Ruby API has method calling the basic API, the extended API, and the advanced API as modules of Ruby. Moreover, CGI scripts for administration of databases, file uploading, and full-text search are provided.

Wide Portability

QDBM is implemented being based on syntax of ANSI C (C89) and using only APIs defined in ANSI C or POSIX. Thus, QDBM works on most UNIX and its compatible OSs. As for C API, checking operations have been done at least on the following platforms.

  • Linux (2.2, 2.4, 2.6) (IA32, IA64, AMD64, PA-RISC, Alpha, PowerPC, M68000, ARM)
  • FreeBSD (4.9, 5.0, 5.1, 5.2, 5.3) (IA32, IA64, SPARC, Alpha)
  • NetBSD (1.6) (IA32)
  • OpenBSD (3.4) (IA32)
  • SunOS (5.6, 5.7, 5.8, 5.9, 5.10) (IA32, SPARC)
  • HP-UX (11.11, 11.23) (IA64, PA-RISC)
  • AIX (5.2) (POWER)
  • Windows (2000, XP) (IA32, IA64, AMD64) (Cygwin, MinGW, Visual C++)
  • Mac OS X (10.2, 10.3, 10.4) (IA32, PowerPC)
  • Tru64 (5.1) (Alpha)
  • RISC OS (5.03) (ARM)

Although a database file created by QDBM depends on byte order of the processor, to do with it, utilities to dump data in format which is independent to byte orders are provided.


Installation

Preparation

To install QDBM from a source package, GCC of 2.8 or later version and `make' are required.

When an archive file of QDBM is extracted, change the current working directory to the generated directory and perform installation.

Usual Steps

Follow the procedures below on Linux, BSD, or SunOS.

Run the configuration script.

./configure

Build programs.

make

Perform self-diagnostic test.

make check

Install programs. This operation must be carried out by the root user.

make install

Using GNU Libtool

If above steps do not work, try the following steps. This way needs GNU Libtool of 1.5 or later version.

Run the configuration script.

./configure

Build programs.

make -f LTmakefile

Perform self-diagnostic test.

make -f LTmakefile check

Install programs. This operation must be carried out by the root user.

make -f LTmakefile install

Result

When a series of work finishes, the following files will be installed. As for the rest, manuals will be installed under `/usr/local/man/man1' and '/usr/local/man/man3', other documents will be installed under `/usr/local/share/qdbm'. A configuration file for `pkg-config' will be installed under `/usr/local/lib/pkgconfig'.

/usr/local/include/depot.h
/usr/local/include/curia.h
/usr/local/include/relic.h
/usr/local/include/hovel.h
/usr/local/include/cabin.h
/usr/local/include/villa.h
/usr/local/include/vista.h
/usr/local/include/odeum.h
/usr/local/lib/libqdbm.a
/usr/local/lib/libqdbm.so.14.14.0
/usr/local/lib/libqdbm.so.14
/usr/local/lib/libqdbm.so
/usr/local/bin/dpmgr
/usr/local/bin/dptest
/usr/local/bin/dptsv
/usr/local/bin/crmgr
/usr/local/bin/crtest
/usr/local/bin/crtsv
/usr/local/bin/rlmgr
/usr/local/bin/rltest
/usr/local/bin/hvmgr
/usr/local/bin/hvtest
/usr/local/bin/cbtest
/usr/local/bin/cbcodec
/usr/local/bin/vlmgr
/usr/local/bin/vltest
/usr/local/bin/vltsv
/usr/local/bin/odmgr
/usr/local/bin/odtest
/usr/local/bin/odidx
/usr/local/bin/qmttest

When you run a program linked dynamically to `libqdbm.so', the library search path should include `/usr/local/lib'. You can set the library search path with the environment variable `LD_LIBRARY_PATH'.

To uninstall QDBM, execute the following command after `./configure'. This operation must be carried out by the root user.

make uninstall

If an old version of QDBM is installed on your system, uninstall it before installation of a new one.

The other APIs except for C nor CGI scripts are not installed by default. Refer to `plus/xspex.html' to know how to install the C++ API. Refer to `java/jspex.html' to know how to install the Java API. Refer to `perl/plspex.html' to know how to install the Perl API. Refer to `ruby/rbspex.html' to know how to install the Ruby API. Refer to `cgi/cgispex.html' to know how to install the CGI script.

To install QDBM from such a binary package as RPM, refer to the manual of the package manager. For example, if you use RPM, execute like the following command by the root user.

rpm -ivh qdbm-1.x.x-x.i386.rpm

For Windows

On Windows (Cygwin), you should follow the procedures below for installation.

Run the configuration script.

./configure

Build programs.

make win

Perform self-diagnostic test.

make check-win

Install programs. As well, perform `make uninstall-win' to uninstall them.

make install-win

On Windows, the import library `libqdbm.dll.a' is created as well as the static library `libqdbm.a', and the dynamic linking library `qdbm.dll' is created instead of such shared libraries as `libqdbm.so'. `qdbm.dll' is installed into `/usr/local/bin'.

In order to build QDBM using MinGW on Cygwin, you should perform `make mingw' instead of `make win'. With the UNIX emulation layer of Cygwin, generated programs depend on `cygwin1.dll' (they come under GNU GPL). This problem is solved by linking them to the Win32 native DLL with MinGW.

In order to build QDBM using Visual C++, you should edit `VCmakefile' and set the search paths for libraries and headers. And perform `nmake /f VCMakefile'. Applications linking to `qdbm.dll' should link to `msvcrt.dll' by `/MD' or `/MDd' option of the compiler. Refer to `VCmakefile' for detail configurations.

For Mac OS X

On Mac OS X (Darwin), you should follow the procedures below for installation.

Run the configuration script.

./configure

Build programs.

make mac

Perform self-diagnostic test.

make check-mac

Install programs. As well, perform `make uninstall-mac' to uninstall them.

make install-mac

On Mac OS X, `libqdbm.dylib' and so on are created instead of `libqdbm.so' and so on. You can set the library search path with the environment variable `DYLD_LIBRARY_PATH'.

For HP-UX

On HP-UX, you should follow the procedures below for installation.

Run the configuration script.

./configure

Build programs.

make hpux

Perform self-diagnostic test.

make check-hpux

Install programs. As well, perform `make uninstall-hpux' to uninstall them.

make install-hpux

On HP-UX, `libqdbm.sl' is created instead of `libqdbm.so' and so on. You can set the library search path with the environment variable `SHLIB_PATH'.

For RISC OS

On RISC OS, you should follow the procedures below for installation.

Build programs. As `cc' is used for compilation by default, if you want to use `gcc', add the argument `CC=gcc'.

make -f RISCmakefile

When a series of work finishes, the library file `libqdbm' and such commands as `dpmgr' are generated. Because how to install them is not defined, copy them manually for installation. As with it, such header files as `depot.h' should be installed manually.

Detail Configurations

You can configure building processes by the following optional arguments of `./configure'.

  • --enable-debug : build for debugging. Enable debugging symbols, do not perform optimization, and perform static linking.
  • --enable-devel : build for development. Enable debugging symbols, perform optimization, and perform dynamic linking.
  • --enable-stable : build for stable release. Perform conservative optimization, and perform dynamic linking.
  • --enable-pthread : feature POSIX thread and treat global variables as thread specific data.
  • --disable-lock : build for environments without file locking.
  • --disable-mmap : build for environments without memory mapping.
  • --enable-zlib : feature ZLIB compression for B+ tree and inverted index.
  • --enable-lzo : feature LZO compression for B+ tree and inverted index.
  • --enable-bzip : feature BZIP2 compression for B+ tree and inverted index.
  • --enable-iconv : feature ICONV utilities for conversion of character encodings.

Usually, QDBM and its applications can be built without any dependency on non-standard libraries except for `libqdbm.*'. However, they depend on `libpthread.*' if POSIX thread is enabled, and they depend on `libz.*' if ZLIB is enabled, and they depend on `liblzo2.*' if LZO is enabled, and they depend on `libbz2.*' if BZIP2 is enabled, and they depend on `libiconv.*' if ICONV is enabled.

Because the license of LZO is GNU GPL, note that applications linking to `liblzo2.*' should meet commitments of GNU GPL.


Depot: Basic API

Overview

Depot is the basic API of QDBM. Almost all features for managing a database provided by QDBM are implemented by Depot. Other APIs are no more than wrappers of Depot. Depot is the fastest in all APIs of QDBM.

In order to use Depot, you should include `depot.h' and `stdlib.h' in the source files. Usually, the following description will be near the beginning of a source file.

#include <depot.h>
#include <stdlib.h>

A pointer to `DEPOT' is used as a database handle. It is like that some file I/O routines of `stdio.h' use a pointer to `FILE'. A database handle is opened with the function `dpopen' and closed with `dpclose'. You should not refer directly to any member of the handle. If a fatal error occurs in a database, any access method via the handle except `dpclose' will not work and return error status. Although a process is allowed to use multiple database handles at the same time, handles of the same database file should not be used.

API

The external variable `dpversion' is the string containing the version information.

extern const char *dpversion;

The external variable `dpecode' is assigned with the last happened error code. Refer to `depot.h' for details of the error codes.

extern int dpecode;
The initial value of this variable is `DP_ENOERR'. The other values are `DP_EFATAL', `DP_EMODE', `DP_EBROKEN', `DP_EKEEP', `DP_ENOITEM', `DP_EALLOC', `DP_EMAP', `DP_EOPEN', `DP_ECLOSE', `DP_ETRUNC', `DP_ESYNC', `DP_ESTAT', `DP_ESEEK', `DP_EREAD', `DP_EWRITE', `DP_ELOCK', `DP_EUNLINK', `DP_EMKDIR', `DP_ERMDIR', and `DP_EMISC'.

The function `dperrmsg' is used in order to get a message string corresponding to an error code.

const char *dperrmsg(int ecode);
`ecode' specifies an error code. The return value is the message string of the error code. The region of the return value is not writable.

The function `dpopen' is used in order to get a database handle.

DEPOT *dpopen(const char *name, int omode, int bnum);
`name' specifies the name of a database file. `omode' specifies the connection mode: `DP_OWRITER' as a writer, `DP_OREADER' as a reader. If the mode is `DP_OWRITER', the following may be added by bitwise or: `DP_OCREAT', which means it creates a new database if not exist, `DP_OTRUNC', which means it creates a new database regardless if one exists. Both of `DP_OREADER' and `DP_OWRITER' can be added to by bitwise or: `DP_ONOLCK', which means it opens a database file without file locking, or `DP_OLCKNB', which means locking is performed without blocking. `DP_OCREAT' can be added to by bitwise or: `DP_OSPARSE', which means it creates a database file as a sparse file. `bnum' specifies the number of elements of the bucket array. If it is not more than 0, the default value is specified. The size of a bucket array is determined on creating, and can not be changed except for by optimization of the database. Suggested size of a bucket array is about from 0.5 to 4 times of the number of all records to store. The return value is the database handle or `NULL' if it is not successful. While connecting as a writer, an exclusive lock is invoked to the database file. While connecting as a reader, a shared lock is invoked to the database file. The thread blocks until the lock is achieved. If `DP_ONOLCK' is used, the application is responsible for exclusion control.

The function `dpclose' is used in order to close a database handle.

int dpclose(DEPOT *depot);
`depot' specifies a database handle. If successful, the return value is true, else, it is false. Because the region of a closed handle is released, it becomes impossible to use the handle. Updating a database is assured to be written when the handle is closed. If a writer opens a database but does not close it appropriately, the database will be broken.

The function `dpput' is used in order to store a record.

int dpput(DEPOT *depot, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int dmode);
`depot' specifies a database handle connected as a writer. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `vbuf' specifies the pointer to the region of a value. `vsiz' specifies the size of the region of the value. If it is negative, the size is assigned with `strlen(vbuf)'. `dmode' specifies behavior when the key overlaps, by the following values: `DP_DOVER', which means the specified value overwrites the existing one, `DP_DKEEP', which means the existing value is kept, `DP_DCAT', which means the specified value is concatenated at the end of the existing value. If successful, the return value is true, else, it is false.

The function `dpout' is used in order to delete a record.

int dpout(DEPOT *depot, const char *kbuf, int ksiz);
`depot' specifies a database handle connected as a writer. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. If successful, the return value is true, else, it is false. False is returned when no record corresponds to the specified key.

The function `dpget' is used in order to retrieve a record.

char *dpget(DEPOT *depot, const char *kbuf, int ksiz, int start, int max, int *sp);
`depot' specifies a database handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `start' specifies the offset address of the beginning of the region of the value to be read. `max' specifies the max size to be read. If it is negative, the size to read is unlimited. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the region of the value of the corresponding record, else, it is `NULL'. `NULL' is returned when no record corresponds to the specified key or the size of the value of the corresponding record is less than `start'. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.

The function `dpgetwb' is used in order to retrieve a record and write the value into a buffer.

int dpgetwb(DEPOT *depot, const char *kbuf, int ksiz, int start, int max, char *vbuf);
`depot' specifies a database handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `start' specifies the offset address of the beginning of the region of the value to be read. `max' specifies the max size to be read. It shuld be equal to or less than the size of the writing buffer. `vbuf' specifies the pointer to a buffer into which the value of the corresponding record is written. If successful, the return value is the size of the written data, else, it is -1. -1 is returned when no record corresponds to the specified key or the size of the value of the corresponding record is less than `start'. Note that no additional zero code is appended at the end of the region of the writing buffer.

The function `dpvsiz' is used in order to get the size of the value of a record.

int dpvsiz(DEPOT *depot, const char *kbuf, int ksiz);
`depot' specifies a database handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. If successful, the return value is the size of the value of the corresponding record, else, it is -1. Because this function does not read the entity of a record, it is faster than `dpget'.

The function `dpiterinit' is used in order to initialize the iterator of a database handle.

int dpiterinit(DEPOT *depot);
`depot' specifies a database handle. If successful, the return value is true, else, it is false. The iterator is used in order to access the key of every record stored in a database.

The function `dpiternext' is used in order to get the next key of the iterator.

char *dpiternext(DEPOT *depot, int *sp);
`depot' specifies a database handle. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the region of the next key, else, it is `NULL'. `NULL' is returned when no record is to be get out of the iterator. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. It is possible to access every record by iteration of calling this function. However, it is not assured if updating the database is occurred while the iteration. Besides, the order of this traversal access method is arbitrary, so it is not assured that the order of storing matches the one of the traversal access.

The function `dpsetalign' is used in order to set alignment of a database handle.

int dpsetalign(DEPOT *depot, int align);
`depot' specifies a database handle connected as a writer. `align' specifies the size of alignment. If successful, the return value is true, else, it is false. If alignment is set to a database, the efficiency of overwriting values is improved. The size of alignment is suggested to be average size of the values of the records to be stored. If alignment is positive, padding whose size is multiple number of the alignment is placed. If alignment is negative, as `vsiz' is the size of a value, the size of padding is calculated with `(vsiz / pow(2, abs(align) - 1))'. Because alignment setting is not saved in a database, you should specify alignment every opening a database.

The function `dpsetfbpsiz' is used in order to set the size of the free block pool of a database handle.

int dpsetfbpsiz(DEPOT *depot, int size);
`depot' specifies a database handle connected as a writer. `size' specifies the size of the free block pool of a database. If successful, the return value is true, else, it is false. The default size of the free block pool is 16. If the size is greater, the space efficiency of overwriting values is improved with the time efficiency sacrificed.

The function `dpsync' is used in order to synchronize updating contents with the file and the device.

int dpsync(DEPOT *depot);
`depot' specifies a database handle connected as a writer. If successful, the return value is true, else, it is false. This function is useful when another process uses the connected database file.

The function `dpoptimize' is used in order to optimize a database.

int dpoptimize(DEPOT *depot, int bnum);
`depot' specifies a database handle connected as a writer. `bnum' specifies the number of the elements of the bucket array. If it is not more than 0, the default value is specified. If successful, the return value is true, else, it is false. In an alternating succession of deleting and storing with overwrite or concatenate, dispensable regions accumulate. This function is useful to do away with them.

The function `dpname' is used in order to get the name of a database.

char *dpname(DEPOT *depot);
`depot' specifies a database handle. If successful, the return value is the pointer to the region of the name of the database, else, it is `NULL'. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.

The function `dpfsiz' is used in order to get the size of a database file.

int dpfsiz(DEPOT *depot);
`depot' specifies a database handle. If successful, the return value is the size of the database file, else, it is -1.

The function `dpbnum' is used in order to get the number of the elements of the bucket array.

int dpbnum(DEPOT *depot);
`depot' specifies a database handle. If successful, the return value is the number of the elements of the bucket array, else, it is -1.

The function `dpbusenum' is used in order to get the number of the used elements of the bucket array.

int dpbusenum(DEPOT *depot);
`depot' specifies a database handle. If successful, the return value is the number of the used elements of the bucket array, else, it is -1. This function is inefficient because it accesses all elements of the bucket array.

The function `dprnum' is used in order to get the number of the records stored in a database.

int dprnum(DEPOT *depot);
`depot' specifies a database handle. If successful, the return value is the number of the records stored in the database, else, it is -1.

The function `dpwritable' is used in order to check whether a database handle is a writer or not.

int dpwritable(DEPOT *depot);
`depot' specifies a database handle. The return value is true if the handle is a writer, false if not.

The function `dpfatalerror' is used in order to check whether a database has a fatal error or not.

int dpfatalerror(DEPOT *depot);
`depot' specifies a database handle. The return value is true if the database has a fatal error, false if not.

The function `dpinode' is used in order to get the inode number of a database file.

int dpinode(DEPOT *depot);
`depot' specifies a database handle. The return value is the inode number of the database file.

The function `dpmtime' is used in order to get the last modified time of a database.

time_t dpmtime(DEPOT *depot);
`depot' specifies a database handle. The return value is the last modified time of the database.

The function `dpfdesc' is used in order to get the file descriptor of a database file.

int dpfdesc(DEPOT *depot);
`depot' specifies a database handle. The return value is the file descriptor of the database file. Handling the file descriptor of a database file directly is not suggested.

The function `dpremove' is used in order to remove a database file.

int dpremove(const char *name);
`name' specifies the name of a database file. If successful, the return value is true, else, it is false.

The function `dprepair' is used in order to repair a broken database file.

int dprepair(const char *name);
`name' specifies the name of a database file. If successful, the return value is true, else, it is false. There is no guarantee that all records in a repaired database file correspond to the original or expected state.

The function `dpexportdb' is used in order to dump all records as endian independent data.

int dpexportdb(DEPOT *depot, const char *name);
`depot' specifies a database handle. `name' specifies the name of an output file. If successful, the return value is true, else, it is false.

The function `dpimportdb' is used in order to load all records from endian independent data.

int dpimportdb(DEPOT *depot, const char *name);
`depot' specifies a database handle connected as a writer. The database of the handle must be empty. `name' specifies the name of an input file. If successful, the return value is true, else, it is false.

The function `dpsnaffle' is used in order to retrieve a record directly from a database file.

char *dpsnaffle(const char *name, const char *kbuf, int ksiz, int *sp);
`name' specifies the name of a database file. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the region of the value of the corresponding record, else, it is `NULL'. `NULL' is returned when no record corresponds to the specified key. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. Although this function can be used even while the database file is locked by another process, it is not assured that recent updated is reflected.

The function `dpinnerhash' is a hash function used inside Depot.

int dpinnerhash(const char *kbuf, int ksiz);
`kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. The return value is the hash value of 31 bits length computed from the key. This function is useful when an application calculates the state of the inside bucket array.

The function `dpouterhash' is a hash function which is independent from the hash functions used inside Depot.

int dpouterhash(const char *kbuf, int ksiz);
`kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. The return value is the hash value of 31 bits length computed from the key. This function is useful when an application uses its own hash algorithm outside Depot.

The function `dpprimenum' is used in order to get a natural prime number not less than a number.

int dpprimenum(int num);
`num' specified a natural number. The return value is a natural prime number not less than the specified number. This function is useful when an application determines the size of a bucket array of its own hash algorithm.

Examples

The following example stores and retrieves a phone number, using the name as the key.

#include <depot.h>
#include <stdlib.h>
#include <stdio.h>

#define NAME     "mikio"
#define NUMBER   "000-1234-5678"
#define DBNAME   "book"

int main(int argc, char **argv){
  DEPOT *depot;
  char *val;

  /* open the database */
  if(!(depot = dpopen(DBNAME, DP_OWRITER | DP_OCREAT, -1))){
    fprintf(stderr, "dpopen: %s\n", dperrmsg(dpecode));
    return 1;
  }

  /* store the record */
  if(!dpput(depot, NAME, -1, NUMBER, -1, DP_DOVER)){
    fprintf(stderr, "dpput: %s\n", dperrmsg(dpecode));
  }

  /* retrieve the record */
  if(!(val = dpget(depot, NAME, -1, 0, -1, NULL))){
    fprintf(stderr, "dpget: %s\n", dperrmsg(dpecode));
  } else {
    printf("Name: %s\n", NAME);
    printf("Number: %s\n", val);
    free(val);
  }

  /* close the database */
  if(!dpclose(depot)){
    fprintf(stderr, "dpclose: %s\n", dperrmsg(dpecode));
    return 1;
  }

  return 0;
}

The following example shows all records of the database.

#include <depot.h>
#include <stdlib.h>
#include <stdio.h>

#define DBNAME   "book"

int main(int argc, char **argv){
  DEPOT *depot;
  char *key, *val;

  /* open the database */
  if(!(depot = dpopen(DBNAME, DP_OREADER, -1))){
    fprintf(stderr, "dpopen: %s\n", dperrmsg(dpecode));
    return 1;
  }

  /* initialize the iterator */
  if(!dpiterinit(depot)){
    fprintf(stderr, "dpiterinit: %s\n", dperrmsg(dpecode));
  }

  /* scan with the iterator */
  while((key = dpiternext(depot, NULL)) != NULL){
    if(!(val = dpget(depot, key, -1, 0, -1, NULL))){
      fprintf(stderr, "dpget: %s\n", dperrmsg(dpecode));
      free(key);
      break;
    }
    printf("%s: %s\n", key, val);
    free(val);
    free(key);
  }

  /* close the database */
  if(!dpclose(depot)){
    fprintf(stderr, "dpclose: %s\n", dperrmsg(dpecode));
    return 1;
  }

  return 0;
}

Notes

For building a program using Depot, the program should be linked with a library file `libqdbm.a' or `libqdbm.so'. For example, the following command is executed to build `sample' from `sample.c'.

gcc -I/usr/local/include -o sample sample.c -L/usr/local/lib -lqdbm

If QDBM was built with POSIX thread enabled, the global variable `dpecode' is treated as thread specific data, and functions of Depot are reentrant. In that case, they are thread-safe as long as a handle is not accessed by threads at the same time, on the assumption that `errno', `malloc', and so on are thread-safe.


Commands for Depot

Depot has the following command line interfaces.

The command `dpmgr' is a utility for debugging Depot and its applications. It features editing and checking of a database. It can be used for database applications with shell scripts. This command is used in the following format. `name' specifies a database name. `key' specifies the key of a record. `val' specifies the value of a record.

dpmgr create [-s] [-bnum num] name
Create a database file.
dpmgr put [-kx|-ki] [-vx|-vi|-vf] [-keep|-cat] [-na] name key val
Store a record with a key and a value.
dpmgr out [-kx|-ki] name key
Delete a record with a key.
dpmgr get [-nl] [-kx|-ki] [-start num] [-max num] [-ox] [-n] name key
Retrieve a record with a key and output it to the standard output.
dpmgr list [-nl] [-k|-v] [-ox] name
List all keys and values delimited with tab and line-feed to the standard output.
dpmgr optimize [-bnum num] [-na] name
Optimize a database.
dpmgr inform [-nl] name
Output miscellaneous information to the standard output.
dpmgr remove name
Remove a database file.
dpmgr repair name
Repair a broken database file.
dpmgr exportdb name file
Dump all records as endian independent data.
dpmgr importdb [-bnum num] name file
Load all records from endian independent data.
dpmgr snaffle [-kx|-ki] [-ox] [-n] name key
Retrieve a record from a locked database with a key and output it to the standard output.
dpmgr version
Output version information of QDBM to the standard output.

Options feature the following.

  • -s : make the file sparse.
  • -bnum num : specify the number of the elements of the bucket array.
  • -kx : treat `key' as a binary expression of hexadecimal notation.
  • -ki : treat `key' as an integer expression of decimal notation.
  • -vx : treat `val' as a binary expression of hexadecimal notation.
  • -vi : treat `val' as an integer expression of decimal notation.
  • -vf : read the value from a file specified with `val'.
  • -keep : specify the storing mode for `DP_DKEEP'.
  • -cat : specify the storing mode for `DP_DCAT'.
  • -na : do not set alignment.
  • -nl : open the database without file locking.
  • -start : specify the beginning offset of a value to fetch.
  • -max : specify the max size of a value to fetch.
  • -ox : treat the output as a binary expression of hexadecimal notation.
  • -n : do not output the tailing newline.
  • -k : output keys only.
  • -v : output values only.

This command returns 0 on success, another on failure. The environment variable `QDBMDBGFD' specifies the file descriptor to output the history of updating the variable `dpecode'.

The command `dptest' is a utility for facility test and performance test. Check a database generated by the command or measure the execution time of the command. This command is used in the following format. `name' specifies a database name. `rnum' specifies the number of the records. `bnum' specifies the number of the elements of the bucket array. `pnum' specifies the number of patterns of the keys. `align' specifies the basic size of alignment. `fbpsiz' specifies the size of the free block pool.

dptest write [-s] name rnum bnum
Store records with keys of 8 bytes. They change as `00000001', `00000002'...
dptest read [-wb] name
Retrieve all records of the database above.
dptest rcat [-c] name rnum bnum pnum align fbpsiz
Store records with partway duplicated keys using concatenate mode.
dptest combo name
Perform combination test of various operations.
dptest wicked [-c] name rnum
Perform updating operations selected at random.

Options feature the following.

  • -s : make the file sparse.
  • -wb : use the function `dpgetwb' instead of the function `dpget'.
  • -c : perform comparison test with map of Cabin.

This command returns 0 on success, another on failure. The environment variable `QDBMDBGFD' specifies the file descriptor to output the history of updating the variable `dpecode'.

The command `dptsv' features mutual conversion between a database of Depot and a TSV text. This command is useful when data exchange with another version of QDBM or another DBM, or when data exchange between systems which have different byte orders. This command is used in the following format. `name' specifies a database name. The subcommand `export' reads TSV data from the standard input. If a key overlaps, the latter is adopted. `-bnum' specifies the number of the elements of the bucket array. The subcommand `import' writes TSV data to the standard output.

dptsv import [-bnum num] [-bin] name
Create a database from TSV.
dptsv export [-bin] name
Write TSV data of a database.

Options feature the following.

  • -bnum num : specify the number of the elements of the bucket array.
  • -bin : treat records as Base64 format.

This command returns 0 on success, another on failure.

Commands of Depot realize a simple database system. For example, to make a database to search `/etc/password' by a user name, perform the following command.

cat /etc/passwd | tr ':' '\t' | dptsv import casket

Thus, to retrieve the information of a user `mikio', perform the following command.

dpmgr get casket mikio

It is easy to implement functions upsides with these commands, using the API of Depot.


Curia: Extended API

Overview

Curia is the extended API of QDBM. It provides routines for managing multiple database files in a directory. Restrictions of some file systems that the size of each file is limited are escaped by dividing a database file into two or more. If the database files deploy on multiple devices, the scalability is improved.

Although Depot creates a database with a file name, Curia creates a database with a directory name. A database file named as `depot' is placed in the specified directory. Although it keeps the attribute of the database, it does not keep the entities of the records. Besides, sub directories are created by the number of division of the database, named with 4 digits. The database files are placed in the subdirectories. The entities of the records are stored in the database file. For example, in the case that a database directory named as `casket' and the number of division is 3, `casket/depot', `casket/0001/depot', `casket/0002/depot' and `casket/0003/depot' are created. No error occurs even if the namesake directory exists when creating a database. So, if sub directories exists and some devices are mounted on the sub directories, the database files deploy on the multiple devices.

Curia features managing large objects. Although usual records are stored in some database files, records of large objects are stored in individual files. Because the files of large objects are deployed in different directories named with the hash values, the access speed is part-way robust although it is slower than the speed of usual records. Large and not often accessed data should be secluded as large objects. By doing this, the access speed of usual records is improved. The directory hierarchies of large objects are placed in the directory named as `lob' in the sub directories of the database. Because the key spaces of the usual records and the large objects are different, the operations keep out of each other.

In order to use Curia, you should include `depot.h', `curia.h' and `stdlib.h' in the source files. Usually, the following description will be near the beginning of a source file.

#include <depot.h>
#include <curia.h>
#include <stdlib.h>

A pointer to `CURIA' is used as a database handle. It is like that some file I/O routines of `stdio.h' use a pointer to `FILE'. A database handle is opened with the function `cropen' and closed with `crclose'. You should not refer directly to any member of the handle. If a fatal error occurs in a database, any access method via the handle except `crclose' will not work and return error status. Although a process is allowed to use multiple database handles at the same time, handles of the same database directory should not be used.

Curia also assign the external variable `dpecode' with the error code. The function `dperrmsg' is used in order to get the message of the error code.

API

The function `cropen' is used in order to get a database handle.

CURIA *cropen(const char *name, int omode, int bnum, int dnum);
`name' specifies the name of a database directory. `omode' specifies the connection mode: `CR_OWRITER' as a writer, `CR_OREADER' as a reader. If the mode is `CR_OWRITER', the following may be added by bitwise or: `CR_OCREAT', which means it creates a new database if not exist, `CR_OTRUNC', which means it creates a new database regardless if one exists. Both of `CR_OREADER' and `CR_OWRITER' can be added to by bitwise or: `CR_ONOLCK', which means it opens a database directory without file locking, or `CR_OLCKNB', which means locking is performed without blocking. `CR_OCREAT' can be added to by bitwise or: `CR_OSPARSE', which means it creates database files as sparse files. `bnum' specifies the number of elements of each bucket array. If it is not more than 0, the default value is specified. The size of each bucket array is determined on creating, and can not be changed except for by optimization of the database. Suggested size of each bucket array is about from 0.5 to 4 times of the number of all records to store. `dnum' specifies the number of division of the database. If it is not more than 0, the default value is specified. The number of division can not be changed from the initial value. The max number of division is 512. The return value is the database handle or `NULL' if it is not successful. While connecting as a writer, an exclusive lock is invoked to the database directory. While connecting as a reader, a shared lock is invoked to the database directory. The thread blocks until the lock is achieved. If `CR_ONOLCK' is used, the application is responsible for exclusion control.

The function `crclose' is used in order to close a database handle.

int crclose(CURIA *curia);
`curia' specifies a database handle. If successful, the return value is true, else, it is false. Because the region of a closed handle is released, it becomes impossible to use the handle. Updating a database is assured to be written when the handle is closed. If a writer opens a database but does not close it appropriately, the database will be broken.

The function `crput' is used in order to store a record.

int crput(CURIA *curia, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int dmode);
`curia' specifies a database handle connected as a writer. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `vbuf' specifies the pointer to the region of a value. `vsiz' specifies the size of the region of the value. If it is negative, the size is assigned with `strlen(vbuf)'. `dmode' specifies behavior when the key overlaps, by the following values: `CR_DOVER', which means the specified value overwrites the existing one, `CR_DKEEP', which means the existing value is kept, `CR_DCAT', which means the specified value is concatenated at the end of the existing value. If successful, the return value is true, else, it is false.

The function `crout' is used in order to delete a record.

int crout(CURIA *curia, const char *kbuf, int ksiz);
`curia' specifies a database handle connected as a writer. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. If successful, the return value is true, else, it is false. False is returned when no record corresponds to the specified key.

The function `crget' is used in order to retrieve a record.

char *crget(CURIA *curia, const char *kbuf, int ksiz, int start, int max, int *sp);
`curia' specifies a database handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `start' specifies the offset address of the beginning of the region of the value to be read. `max' specifies the max size to be read. If it is negative, the size to read is unlimited. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the region of the value of the corresponding record, else, it is `NULL'. `NULL' is returned when no record corresponds to the specified key or the size of the value of the corresponding record is less than `start'. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.

The function `crgetwb' is used in order to retrieve a record and write the value into a buffer.

int crgetwb(CURIA *curia, const char *kbuf, int ksiz, int start, int max, char *vbuf);
`curia' specifies a database handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `start' specifies the offset address of the beginning of the region of the value to be read. `max' specifies the max size to be read. It shuld be equal to or less than the size of the writing buffer. `vbuf' specifies the pointer to a buffer into which the value of the corresponding record is written. If successful, the return value is the size of the written data, else, it is -1. -1 is returned when no record corresponds to the specified key or the size of the value of the corresponding record is less than `start'. Note that no additional zero code is appended at the end of the region of the writing buffer.

The function `crvsiz' is used in order to get the size of the value of a record.

int crvsiz(CURIA *curia, const char *kbuf, int ksiz);
`curia' specifies a database handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. If successful, the return value is the size of the value of the corresponding record, else, it is -1. Because this function does not read the entity of a record, it is faster than `crget'.

The function `criterinit' is used in order to initialize the iterator of a database handle.

int criterinit(CURIA *curia);
`curia' specifies a database handle. If successful, the return value is true, else, it is false. The iterator is used in order to access the key of every record stored in a database.

The function `criternext' is used in order to get the next key of the iterator.

char *criternext(CURIA *curia, int *sp);
`curia' specifies a database handle. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the region of the next key, else, it is `NULL'. `NULL' is returned when no record is to be get out of the iterator. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. It is possible to access every record by iteration of calling this function. However, it is not assured if updating the database is occurred while the iteration. Besides, the order of this traversal access method is arbitrary, so it is not assured that the order of storing matches the one of the traversal access.

The function `crsetalign' is used in order to set alignment of a database handle.

int crsetalign(CURIA *curia, int align);
`curia' specifies a database handle connected as a writer. `align' specifies the size of alignment. If successful, the return value is true, else, it is false. If alignment is set to a database, the efficiency of overwriting values is improved. The size of alignment is suggested to be average size of the values of the records to be stored. If alignment is positive, padding whose size is multiple number of the alignment is placed. If alignment is negative, as `vsiz' is the size of a value, the size of padding is calculated with `(vsiz / pow(2, abs(align) - 1))'. Because alignment setting is not saved in a database, you should specify alignment every opening a database.

The function `crsetfbpsiz' is used in order to set the size of the free block pool of a database handle.

int crsetfbpsiz(CURIA *curia, int size);
`curia' specifies a database handle connected as a writer. `size' specifies the size of the free block pool of a database. If successful, the return value is true, else, it is false. The default size of the free block pool is 16. If the size is greater, the space efficiency of overwriting values is improved with the time efficiency sacrificed.

The function `crsync' is used in order to synchronize updating contents with the files and the devices.

int crsync(CURIA *curia);
`curia' specifies a database handle connected as a writer. If successful, the return value is true, else, it is false. This function is useful when another process uses the connected database directory.

The function `croptimize' is used in order to optimize a database.

int croptimize(CURIA *curia, int bnum);
`curia' specifies a database handle connected as a writer. `bnum' specifies the number of the elements of each bucket array. If it is not more than 0, the default value is specified. In an alternating succession of deleting and storing with overwrite or concatenate, dispensable regions accumulate. This function is useful to do away with them.

The function `crname' is used in order to get the name of a database.

char *crname(CURIA *curia);
`curia' specifies a database handle. If successful, the return value is the pointer to the region of the name of the database, else, it is `NULL'. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.

The function `crfsiz' is used in order to get the total size of database files.

int crfsiz(CURIA *curia);
`curia' specifies a database handle. If successful, the return value is the total size of the database files, else, it is -1. If the total size is more than 2GB, the return value overflows.

The function `crfsizd' is used in order to get the total size of database files as double-precision floating-point number.

double crfsizd(CURIA *curia);
`curia' specifies a database handle. If successful, the return value is the total size of the database files, else, it is -1.0.

The function `crbnum' is used in order to get the total number of the elements of each bucket array.

int crbnum(CURIA *curia);
`curia' specifies a database handle. If successful, the return value is the total number of the elements of each bucket array, else, it is -1.

The function `crbusenum' is used in order to get the total number of the used elements of each bucket array.

int crbusenum(CURIA *curia);
`curia' specifies a database handle. If successful, the return value is the total number of the used elements of each bucket array, else, it is -1. This function is inefficient because it accesses all elements of each bucket array.

The function `crrnum' is used in order to get the number of the records stored in a database.

int crrnum(CURIA *curia);
`curia' specifies a database handle. If successful, the return value is the number of the records stored in the database, else, it is -1.

The function `crwritable' is used in order to check whether a database handle is a writer or not.

int crwritable(CURIA *curia);
`curia' specifies a database handle. The return value is true if the handle is a writer, false if not.

The function `crfatalerror' is used in order to check whether a database has a fatal error or not.

int crfatalerror(CURIA *curia);
`curia' specifies a database handle. The return value is true if the database has a fatal error, false if not.

The function `crinode' is used in order to get the inode number of a database directory.

int crinode(CURIA *curia);
`curia' specifies a database handle. The return value is the inode number of the database directory.

The function `crmtime' is used in order to get the last modified time of a database.

time_t crmtime(CURIA *curia);
`curia' specifies a database handle. The return value is the last modified time of the database.

The function `crremove' is used in order to remove a database directory.

int crremove(const char *name);
`name' specifies the name of a database directory. If successful, the return value is true, else, it is false.

The function `crrepair' is used in order to repair a broken database directory.

int crrepair(const char *name);
`name' specifies the name of a database directory. If successful, the return value is true, else, it is false. There is no guarantee that all records in a repaired database directory correspond to the original or expected state.

The function `crexportdb' is used in order to dump all records as endian independent data.

int crexportdb(CURIA *curia, const char *name);
`curia' specifies a database handle. `name' specifies the name of an output directory. If successful, the return value is true, else, it is false. Note that large objects are ignored.

The function `crimportdb' is used in order to load all records from endian independent data.

int crimportdb(CURIA *curia, const char *name);
`curia' specifies a database handle connected as a writer. The database of the handle must be empty. `name' specifies the name of an input directory. If successful, the return value is true, else, it is false. Note that large objects are ignored.

The function `crsnaffle' is used in order to retrieve a record directly from a database directory.

char *crsnaffle(const char *name, const char *kbuf, int ksiz, int *sp);
`name' specifies the name of a database directory. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the region of the value of the corresponding record, else, it is `NULL'. `NULL' is returned when no record corresponds to the specified key. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. Although this function can be used even while the database directory is locked by another process, it is not assured that recent updated is reflected.

The function `crputlob' is used in order to store a large object.

int crputlob(CURIA *curia, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int dmode);
`curia' specifies a database handle connected as a writer. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `vbuf' specifies the pointer to the region of a value. `vsiz' specifies the size of the region of the value. If it is negative, the size is assigned with `strlen(vbuf)'. `dmode' specifies behavior when the key overlaps, by the following values: `CR_DOVER', which means the specified value overwrites the existing one, `CR_DKEEP', which means the existing value is kept, `CR_DCAT', which means the specified value is concatenated at the end of the existing value. If successful, the return value is true, else, it is false.

The function `croutlob' is used in order to delete a large object.

int croutlob(CURIA *curia, const char *kbuf, int ksiz);
`curia' specifies a database handle connected as a writer. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. If successful, the return value is true, else, it is false. false is returned when no large object corresponds to the specified key.

The function `crgetlob' is used in order to retrieve a large object.

char *crgetlob(CURIA *curia, const char *kbuf, int ksiz, int start, int max, int *sp);
`curia' specifies a database handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `start' specifies the offset address of the beginning of the region of the value to be read. `max' specifies the max size to be read. If it is negative, the size to read is unlimited. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the region of the value of the corresponding large object, else, it is `NULL'. `NULL' is returned when no large object corresponds to the specified key or the size of the value of the corresponding large object is less than `start'. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.

The function `crgetlobfd' is used in order to get the file descriptor of a large object.

int crgetlobfd(CURIA *curia, const char *kbuf, int ksiz);
`curia' specifies a database handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. If successful, the return value is the file descriptor of the corresponding large object, else, it is -1. -1 is returned when no large object corresponds to the specified key. The returned file descriptor is opened with the `open' call. If the database handle was opened as a writer, the descriptor is writable (O_RDWR), else, it is not writable (O_RDONLY). The descriptor should be closed with the `close' call if it is no longer in use.

The function `crvsizlob' is used in order to get the size of the value of a large object.

int crvsizlob(CURIA *curia, const char *kbuf, int ksiz);
`curia' specifies a database handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. If successful, the return value is the size of the value of the corresponding large object, else, it is -1. Because this function does not read the entity of a large object, it is faster than `crgetlob'.

The function `crrnumlob' is used in order to get the number of the large objects stored in a database.

int crrnumlob(CURIA *curia);
`curia' specifies a database handle. If successful, the return value is the number of the large objects stored in the database, else, it is -1.

Examples

The following example stores and retrieves a phone number, using the name as the key.

#include <depot.h>
#include <curia.h>
#include <stdlib.h>
#include <stdio.h>

#define NAME     "mikio"
#define NUMBER   "000-1234-5678"
#define DBNAME   "book"

int main(int argc, char **argv){
  CURIA *curia;
  char *val;

  /* open the database */
  if(!(curia = cropen(DBNAME, CR_OWRITER | CR_OCREAT, -1, -1))){
    fprintf(stderr, "cropen: %s\n", dperrmsg(dpecode));
    return 1;
  }

  /* store the record */
  if(!crput(curia, NAME, -1, NUMBER, -1, CR_DOVER)){
    fprintf(stderr, "crput: %s\n", dperrmsg(dpecode));
  }

  /* retrieve the record */
  if(!(val = crget(curia, NAME, -1, 0, -1, NULL))){
    fprintf(stderr, "crget: %s\n", dperrmsg(dpecode));
  } else {
    printf("Name: %s\n", NAME);
    printf("Number: %s\n", val);
    free(val);
  }

  /* close the database */
  if(!crclose(curia)){
    fprintf(stderr, "crclose: %s\n", dperrmsg(dpecode));
    return 1;
  }

  return 0;
}

The following example shows all records of the database.

#include <depot.h>
#include <curia.h>
#include <stdlib.h>
#include <stdio.h>

#define DBNAME   "book"

int main(int argc, char **argv){
  CURIA *curia;
  char *key, *val;

  /* open the database */
  if(!(curia = cropen(DBNAME, CR_OREADER, -1, -1))){
    fprintf(stderr, "cropen: %s\n", dperrmsg(dpecode));
    return 1;
  }

  /* initialize the iterator */
  if(!criterinit(curia)){
    fprintf(stderr, "criterinit: %s\n", dperrmsg(dpecode));
  }

  /* scan with the iterator */
  while((key = criternext(curia, NULL)) != NULL){
    if(!(val = crget(curia, key, -1, 0, -1, NULL))){
      fprintf(stderr, "crget: %s\n", dperrmsg(dpecode));
      free(key);
      break;
    }
    printf("%s: %s\n", key, val);
    free(val);
    free(key);
  }

  /* close the iterator */
  if(!crclose(curia)){
    fprintf(stderr, "crclose: %s\n", dperrmsg(dpecode));
    return 1;
  }

  return 0;
}

Notes

How to build programs using Curia is the same as the case of Depot.

gcc -I/usr/local/include -o sample sample.c -L/usr/local/lib -lqdbm

If QDBM was built with POSIX thread enabled, the global variable `dpecode' is treated as thread specific data, and functions of Curia are reentrant. In that case, they are thread-safe as long as a handle is not accessed by threads at the same time, on the assumption that `errno', `malloc', and so on are thread-safe.


Commands for Curia

Curia has the following command line interfaces.

The command `crmgr' is a utility for debugging Curia and its applications. It features editing and checking of a database. It can be used for the database applications with shell scripts. This command is used in the following format. `name' specifies a database name. `key' specifies the key of a record. `val' specifies the value of a record.

crmgr create [-s] [-bnum num] [-dnum num] name
Create a database file.
crmgr put [-kx|-ki] [-vx|-vi|-vf] [-keep|-cat] [-lob] [-na] name key val
Store a record with a key and a value.
crmgr out [-kx|-ki] [-lob] name key
Delete a record with a key.
crmgr get [-nl] [-kx|-ki] [-start num] [-max num] [-ox] [-lob] [-n] name key
Retrieve a record with a key and output it to the standard output.
crmgr list [-nl] [-k|-v] [-ox] name
List all keys and values delimited with tab and line-feed to the standard output.
crmgr optimize [-bnum num] [-na] name
Optimize a database.
crmgr inform [-nl] name
Output miscellaneous information to the standard output.
crmgr remove name
Remove a database directory.
crmgr repair name
Repair a broken database directory.
crmgr exportdb name dir
Dump all records as endian independent data.
crmgr importdb [-bnum num] [-dnum num] name dir
Load all records from endian independent data.
crmgr snaffle [-kx|-ki] [-ox] [-n] name key
Retrieve a record from a locked database with a key and output it to the standard output.
crmgr version
Output version information of QDBM to the standard output.

Options feature the following.

  • -s : make the files sparse.
  • -bnum num : specify the number of elements of each bucket array.
  • -dnum num : specify the number of division of the database.
  • -kx : treat `key' as a binary expression of hexadecimal notation.
  • -ki : treat `key' as an integer expression of decimal notation.
  • -vx : treat `val' as a binary expression of hexadecimal notation.
  • -vi : treat `val' as an integer expression of decimal notation.
  • -vf : read the value from a file specified with `val'.
  • -keep : specify the storing mode for `CR_DKEEP'.
  • -cat : specify the storing mode for `CR_DCAT'.
  • -na : do not set alignment.
  • -nl : open the database without file locking.
  • -start : specify the beginning offset of a value to fetch.
  • -max : specify the max size of a value to fetch.
  • -ox : treat the output as a binary expression of hexadecimal notation.
  • -lob : handle large objects.
  • -n : do not output the tailing newline.
  • -k : output keys only.
  • -v : output values only.

This command returns 0 on success, another on failure. The environment variable `QDBMDBGFD' specifies the file descriptor to output the history of updating the variable `dpecode'.

The command `crtest' is a utility for facility test and performance test. Check a database generated by the command or measure the execution time of the command. This command is used in the following format. `name' specifies a database name. `rnum' specifies the number of records. `bnum' specifies the number of elements of a bucket array. `dnum' specifies the number of division of a database. `pnum' specifies the number of patterns of the keys. `align' specifies the basic size of alignment. `fbpsiz' specifies the size of the free block pool.

crtest write [-s] [-lob] name rnum bnum dnum
Store records with keys of 8 bytes. They change as `00000001', `00000002'...
crtest read [-wb] [-lob] name
Retrieve all records of the database above.
crtest rcat [-c] name rnum bnum dnum pnum align fbpsiz
Store records with partway duplicated keys using concatenate mode.
crtest combo name
Perform combination test of various operations.
crtest wicked [-c] name rnum
Perform updating operations selected at random.

Options feature the following.

  • -s : make the files sparse.
  • -lob : handle large objects.
  • -wb : use the function `crgetwb' instead of the function `crget'.
  • -c : perform comparison test with map of Cabin.

This command returns 0 on success, another on failure. The environment variable `QDBMDBGFD' specifies the file descriptor to output the history of updating the variable `dpecode'.

The command `crtsv' features mutual conversion between a database of Curia and a TSV text. This command is useful when data exchange with another version of QDBM or another DBM, or when data exchange between systems which have different byte orders. This command is used in the following format. `name' specifies a database name. The subcommand `export' reads TSV data from the standard input. If a key overlaps, the latter is adopted. `-bnum' specifies the number of the elements of the bucket array. `-dnum' specifies the number of division of the database. The subcommand `import' writes TSV data to the standard output.

crtsv import [-bnum num] [-dnum num] [-bin] name
Create a database from TSV.
crtsv export [-bin] name
Write TSV data of a database.

Options feature the following.

  • -bnum num : specify the number of the elements of the bucket array.
  • -dnum num : specify the number of division of the database.
  • -bin : treat records as Base64 format.

This command returns 0 on success, another on failure.

Commands of Curia realize a simple database system. For example, to make a database to search `/etc/password' by a user name, perform the following command.

cat /etc/passwd | tr ':' '\t' | crtsv import casket

Thus, to retrieve the information of a user `mikio', perform the following command.

crmgr get casket mikio

It is easy to implement functions upsides with these commands, using the API of Curia.


Relic: NDBM-compatible API

Overview

Relic is the API which is compatible with NDBM. So, Relic wraps functions of Depot as API of NDBM. It is easy to port an application from NDBM to QDBM. In most cases, you should only replace the includings of `ndbm.h' with `relic.h' and replace the linking option `-lndbm' with `-lqdbm'.

The original NDBM treats a database as a pair of files. One, `a directory file', has a name with suffix `.dir' and stores a bit map of keys. The other, `a data file', has a name with suffix `.pag' and stores entities of each records. Relic creates the directory file as a mere dummy file and creates the data file as a database. Relic has no restriction about the size of each record. Relic can not handle database files made by the original NDBM.

In order to use Relic, you should include `relic.h', `stdlib.h', `sys/types.h', `sys/stat.h' and `fcntl.h' in the source files. Usually, the following description will be near the beginning of a source file.

#include <relic.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

A pointer to `DBM' is used as a database handle. A database handle is opened with the function `dbm_open' and closed with `dbm_close'. You should not refer directly to any member of a handle.

API

Structures of `datum' type is used in order to give and receive data of keys and values with functions of Relic.

typedef struct { void *dptr; size_t dsize; } datum;
`dptr' specifies the pointer to the region of a key or a value. `dsize' specifies the size of the region.

The function `dbm_open' is used in order to get a database handle.

DBM *dbm_open(char *name, int flags, int mode);
`name' specifies the name of a database. The file names are concatenated with suffixes. `flags' is the same as the one of `open' call, although `O_WRONLY' is treated as `O_RDWR' and additional flags except for `O_CREAT' and `O_TRUNC' have no effect. `mode' specifies the mode of the database file as the one of `open' call does. The return value is the database handle or `NULL' if it is not successful.

The function `dbm_close' is used in order to close a database handle.

void dbm_close(DBM *db);
`db' specifies a database handle. Because the region of the closed handle is released, it becomes impossible to use the handle.

The function `dbm_store' is used in order to store a record.

int dbm_store(DBM *db, datum key, datum content, int flags);
`db' specifies a database handle. `key' specifies a structure of a key. `content' specifies a structure of a value. `flags' specifies behavior when the key overlaps, by the following values: `DBM_REPLACE', which means the specified value overwrites the existing one, `DBM_INSERT', which means the existing value is kept. The return value is 0 if it is successful, 1 if it gives up because of overlaps of the key, -1 if other error occurs.

The function `dbm_delete' is used in order to delete a record.

int dbm_delete(DBM *db, datum key);
`db' specifies a database handle. `key' specifies a structure of a key. The return value is 0 if it is successful, -1 if some errors occur.

The function `dbm_fetch' is used in order to retrieve a record.

datum dbm_fetch(DBM *db, datum key);
`db' specifies a database handle. `key' specifies a structure of a key. The return value is a structure of the result. If a record corresponds, the member `dptr' of the structure is the pointer to the region of the value. If no record corresponds or some errors occur, `dptr' is `NULL'. `dptr' points to the region related with the handle. The region is available until the next time of calling this function with the same handle.

The function `dbm_firstkey' is used in order to get the first key of a database.

datum dbm_firstkey(DBM *db);
`db' specifies a database handle. The return value is a structure of the result. If a record corresponds, the member `dptr' of the structure is the pointer to the region of the first key. If no record corresponds or some errors occur, `dptr' is `NULL'. `dptr' points to the region related with the handle. The region is available until the next time of calling this function or the function `dbm_nextkey' with the same handle.

The function `dbm_nextkey' is used in order to get the next key of a database.

datum dbm_nextkey(DBM *db);
`db' specifies a database handle. The return value is a structure of the result. If a record corresponds, the member `dptr' of the structure is the pointer to the region of the next key. If no record corresponds or some errors occur, `dptr' is `NULL'. `dptr' points to the region related with the handle. The region is available until the next time of calling this function or the function `dbm_firstkey' with the same handle.

The function `dbm_error' is used in order to check whether a database has a fatal error or not.

int dbm_error(DBM *db);
`db' specifies a database handle. The return value is true if the database has a fatal error, false if not.

The function `dbm_clearerr' has no effect.

int dbm_clearerr(DBM *db);
`db' specifies a database handle. The return value is 0. The function is only for compatibility.

The function `dbm_rdonly' is used in order to check whether a handle is read-only or not.

int dbm_rdonly(DBM *db);
`db' specifies a database handle. The return value is true if the handle is read-only, or false if not read-only.

The function `dbm_dirfno' is used in order to get the file descriptor of a directory file.

int dbm_dirfno(DBM *db);
`db' specifies a database handle. The return value is the file descriptor of the directory file.

The function `dbm_pagfno' is used in order to get the file descriptor of a data file.

int dbm_pagfno(DBM *db);
`db' specifies a database handle. The return value is the file descriptor of the data file.

Examples

The following example stores and retrieves a phone number, using the name as the key.

#include <relic.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <string.h>

#define NAME     "mikio"
#define NUMBER   "000-1234-5678"
#define DBNAME   "book"

int main(int argc, char **argv){
  DBM *db;
  datum key, val;
  int i;

  /* open the database */
  if(!(db = dbm_open(DBNAME, O_RDWR | O_CREAT, 00644))){
    perror("dbm_open");
    return 1;
  }

  /* prepare the record */
  key.dptr = NAME;
  key.dsize = strlen(NAME);
  val.dptr = NUMBER;
  val.dsize = strlen(NUMBER);

  /* store the record */
  if(dbm_store(db, key, val, DBM_REPLACE) != 0){
    perror("dbm_store");
  }

  /* retrieve the record */
  val = dbm_fetch(db, key);
  if(val.dptr){
    printf("Name: %s\n", NAME);
    printf("Number: ");
    for(i = 0; i < val.dsize; i++){
      putchar(((char *)val.dptr)[i]);
    }
    putchar('\n');
  } else {
    perror("dbm_fetch");
  }

  /* close the database */
  dbm_close(db);

  return 0;
}

Notes

How to build programs using Relic is the same as the case of Depot. Note that an option to be given to a linker is not `-lndbm', but `-lqdbm'.

gcc -I/usr/local/include -o sample sample.c -L/usr/local/lib -lqdbm

Functions of Relic are thread-safe as long as a handle is not accessed by threads at the same time, on the assumption that `errno', `malloc', and so on are thread-safe.


Commands for Relic

Relic has the following command line interfaces.

The command `rlmgr' is a utility for debugging Relic and its applications. It features editing and checking of a database. It can be used for database applications with shell scripts. This command is used in the following format. `name' specifies a database name. `key' specifies the key of a record. `val' specifies the value of a record.

rlmgr create name
Create a database file.
rlmgr store [-kx] [-vx|-vf] [-insert] name key val
Store a record with a key and a value.
rlmgr delete [-kx] name key
Delete a record with a key.
rlmgr fetch [-kx] [-ox] [-n] name key
Retrieve a record with a key and output to the standard output.
rlmgr list [-ox] name
List all keys and values delimited with tab and line-feed to the standard output.

Options feature the following.

  • -kx : treat `key' as a binary expression of hexadecimal notation.
  • -vx : treat `val' as a binary expression of hexadecimal notation.
  • -vf : read the value from a file specified with `val'.
  • -insert : specify the storing mode for `DBM_INSERT'.
  • -ox : treat the output as a binary expression of hexadecimal notation.
  • -n : do not output the tailing newline.

This command returns 0 on success, another on failure.

The command `rltest' is a utility for facility test and performance test. Check a database generated by the command or measure the execution time of the command. This command is used in the following format. `name' specifies a database name. `rnum' specifies the number of records.

rltest write name rnum
Store records with keys of 8 bytes. They change as `00000001', `00000002'...
rltest read name rnum
Retrieve records of the database above.

This command returns 0 on success, another on failure.


Hovel: GDBM-compatible API

Overview

Hovel is the API which is compatible with GDBM. So, Hovel wraps functions of Depot and Curia as API of GDBM. It is easy to port an application from GDBM to QDBM. In most cases, you should only replace the includings of `gdbm.h' with `hovel.h' and replace the linking option `-lgdbm' with `-lqdbm'. Hovel can not handle database files made by the original GDBM.

In order to use Hovel, you should include `hovel.h', `stdlib.h', `sys/types.h' and `sys/stat.h' in the source files. Usually, the following description will be near the beginning of a source file.

#include <hovel.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>

An object of `GDBM_FILE' is used as a database handle. A database handle is opened with the function `gdbm_open' and closed with `gdbm_close'. You should not refer directly to any member of a handle. Although Hovel works as a wrapper of Depot and handles a database file usually, if you use the function `gdbm_open2' to open the handle, it is possible to make behavior of a handle as a wrapper of Curia and treat a database directory.

API

Structures of `datum' type is used in order to give and receive data of keys and values with functions of Hovel.

typedef struct { char *dptr; size_t dsize; } datum;
`dptr' specifies the pointer to the region of a key or a value. `dsize' specifies the size of the region.

The external variable `gdbm_version' is the string containing the version information.

extern char *gdbm_version;

The external variable `gdbm_errno' is assigned with the last happened error code. Refer to `hovel.h' for details of the error codes.

extern gdbm_error gdbm_errno;
The initial value of this variable is `GDBM_NO_ERROR'. The other values are `GDBM_MALLOC_ERROR', `GDBM_BLOCK_SIZE_ERROR', `GDBM_FILE_OPEN_ERROR', `GDBM_FILE_WRITE_ERROR', `GDBM_FILE_SEEK_ERROR', `GDBM_FILE_READ_ERROR', `GDBM_BAD_MAGIC_NUMBER', `GDBM_EMPTY_DATABASE', `GDBM_CANT_BE_READER', `GDBM_CANT_BE_WRITER', `GDBM_READER_CANT_DELETE', `GDBM_READER_CANT_STORE', `GDBM_READER_CANT_REORGANIZE', `GDBM_UNKNOWN_UPDATE', `GDBM_ITEM_NOT_FOUND', `GDBM_REORGANIZE_FAILED', `GDBM_CANNOT_REPLACE', `GDBM_ILLEGAL_DATA', `GDBM_OPT_ALREADY_SET', and `GDBM_OPT_ILLEGAL'.

The function `gdbm_strerror' is used in order to get a message string corresponding to an error code.

char *gdbm_strerror(gdbm_error gdbmerrno);
`gdbmerrno' specifies an error code. The return value is the message string of the error code. The region of the return value is not writable.

The function `gdbm_open' is used in order to get a database handle after the fashion of GDBM.

GDBM_FILE gdbm_open(char *name, int block_size, int read_write, int mode, void (*fatal_func)(void));
`name' specifies the name of a database. `block_size' is ignored. `read_write' specifies the connection mode: `GDBM_READER' as a reader, `GDBM_WRITER', `GDBM_WRCREAT' and `GDBM_NEWDB' as a writer. `GDBM_WRCREAT' makes a database file or directory if it does not exist. `GDBM_NEWDB' makes a new database even if it exists. You can add the following to writer modes by bitwise or: `GDBM_SYNC', `GDBM_NOLOCK', `GDBM_LOCKNB', `GDBM_FAST', and `GDBM_SPARSE'. `GDBM_SYNC' means a database is synchronized after every updating method. `GDBM_NOLOCK' means a database is opened without file locking. `GDBM_LOCKNB' means file locking is performed without blocking. `GDBM_FAST' is ignored. `GDBM_SPARSE' is an original mode of QDBM and makes database a sparse file. `mode' specifies mode of a database file as the one of `open' call does. `fatal_func' is ignored. The return value is the database handle or `NULL' if it is not successful.

The function `gdbm_open2' is used in order to get a database handle after the fashion of QDBM.

GDBM_FILE gdbm_open2(char *name, int read_write, int mode, int bnum, int dnum, int align);
`name' specifies the name of a database. `read_write' specifies the connection mode: `GDBM_READER' as a reader, `GDBM_WRITER', `GDBM_WRCREAT' and `GDBM_NEWDB' as a writer. `GDBM_WRCREAT' makes a database file or directory if it does not exist. `GDBM_NEWDB' makes a new database even if it exists. You can add the following to writer modes by bitwise or: `GDBM_SYNC', `GDBM_NOLOCK', 'GDBM_LOCKNB', `GDBM_FAST', and `GDBM_SPARSE'. `GDBM_SYNC' means a database is synchronized after every updating method. `GDBM_NOLOCK' means a database is opened without file locking. `GDBM_LOCKNB' means file locking is performed without blocking. `GDBM_FAST' is ignored. `GDBM_SPARSE' is an original mode of QDBM and makes database sparse files. `mode' specifies a mode of a database file or a database directory as the one of `open' or `mkdir' call does. `bnum' specifies the number of elements of each bucket array. If it is not more than 0, the default value is specified. `dnum' specifies the number of division of the database. If it is not more than 0, the returning handle is created as a wrapper of Depot, else, it is as a wrapper of Curia. `align' specifies the basic size of alignment. The return value is the database handle or `NULL' if it is not successful. If the database already exists, whether it is one of Depot or Curia is measured automatically.

The function `gdbm_close' is used in order to close a database handle.

void gdbm_close(GDBM_FILE dbf);
`dbf' specifies a database handle. Because the region of the closed handle is released, it becomes impossible to use the handle.

The function `gdbm_store' is used in order to store a record.

int gdbm_store(GDBM_FILE dbf, datum key, datum content, int flag);
`dbf' specifies a database handle connected as a writer. `key' specifies a structure of a key. `content' specifies a structure of a value. `flag' specifies behavior when the key overlaps, by the following values: `GDBM_REPLACE', which means the specified value overwrites the existing one, `GDBM_INSERT', which means the existing value is kept. The return value is 0 if it is successful, 1 if it gives up because of overlaps of the key, -1 if other error occurs.

The function `gdbm_delete' is used in order to delete a record.

int gdbm_delete(GDBM_FILE dbf, datum key);
`dbf' specifies a database handle connected as a writer. `key' specifies a structure of a key. The return value is 0 if it is successful, -1 if some errors occur.

The function `gdbm_fetch' is used in order to retrieve a record.

datum gdbm_fetch(GDBM_FILE dbf, datum key);
`dbf' specifies a database handle. `key' specifies a structure of a key. The return value is a structure of the result. If a record corresponds, the member `dptr' of the structure is the pointer to the region of the value. If no record corresponds or some errors occur, `dptr' is `NULL'. Because the region pointed to by `dptr' is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.

The function `gdbm_exists' is used in order to check whether a record exists or not.

int gdbm_exists(GDBM_FILE dbf, datum key);
`dbf' specifies a database handle. `key' specifies a structure of a key. The return value is true if a record corresponds and no error occurs, or false, else, it is false.

The function `gdbm_firstkey' is used in order to get the first key of a database.

datum gdbm_firstkey(GDBM_FILE dbf);
`dbf' specifies a database handle. The return value is a structure of the result. If a record corresponds, the member `dptr' of the structure is the pointer to the region of the first key. If no record corresponds or some errors occur, `dptr' is `NULL'. Because the region pointed to by `dptr' is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.

The function `gdbm_nextkey' is used in order to get the next key of a database.

datum gdbm_nextkey(GDBM_FILE dbf, datum key);
`dbf' specifies a database handle. The return value is a structure of the result. If a record corresponds, the member `dptr' of the structure is the pointer to the region of the next key. If no record corresponds or some errors occur, `dptr' is `NULL'. Because the region pointed to by `dptr' is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.

The function `gdbm_sync' is used in order to synchronize updating contents with the file and the device.

void gdbm_sync(GDBM_FILE dbf);
`dbf' specifies a database handle connected as a writer.

The function `gdbm_reorganize' is used in order to reorganize a database.

int gdbm_reorganize(GDBM_FILE dbf);
`dbf' specifies a database handle connected as a writer. If successful, the return value is 0, else -1.

The function `gdbm_fdesc' is used in order to get the file descriptor of a database file.

int gdbm_fdesc(GDBM_FILE dbf);
`dbf' specifies a database handle connected as a writer. The return value is the file descriptor of the database file. If the database is a directory the return value is -1.

The function `gdbm_setopt' has no effect.

int gdbm_setopt(GDBM_FILE dbf, int option, int *value, int size);
`dbf' specifies a database handle. `option' is ignored. `size' is ignored. The return value is 0. The function is only for compatibility.

Examples

The following example stores and retrieves a phone number, using the name as the key.

#include <hovel.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <string.h>

#define NAME     "mikio"
#define NUMBER   "000-1234-5678"
#define DBNAME   "book"

int main(int argc, char **argv){
  GDBM_FILE dbf;
  datum key, val;
  int i;

  /* open the database */
  if(!(dbf = gdbm_open(DBNAME, 0, GDBM_WRCREAT, 00644, NULL))){
    fprintf(stderr, "gdbm_open: %s\n", gdbm_strerror(gdbm_errno));
    return 1;
  }

  /* prepare the record */
  key.dptr = NAME;
  key.dsize = strlen(NAME);
  val.dptr = NUMBER;
  val.dsize = strlen(NUMBER);

  /* store the record */
  if(gdbm_store(dbf, key, val, GDBM_REPLACE) != 0){
    fprintf(stderr, "gdbm_store: %s\n", gdbm_strerror(gdbm_errno));
  }

  /* retrieve the record */
  val = gdbm_fetch(dbf, key);
  if(val.dptr){
    printf("Name: %s\n", NAME);
    printf("Number: ");
    for(i = 0; i < val.dsize; i++){
      putchar(val.dptr[i]);
    }
    putchar('\n');
    free(val.dptr);
  } else {
    fprintf(stderr, "gdbm_fetch: %s\n", gdbm_strerror(gdbm_errno));
  }

  /* close the database */
  gdbm_close(dbf);

  return 0;
}

Notes

How to build programs using Hovel is the same as the case of Depot. Note that an option to be given to a linker is not `-lgdbm', but `-lqdbm'.

gcc -I/usr/local/include -o sample sample.c -L/usr/local/lib -lqdbm

If QDBM was built with POSIX thread enabled, the global variable `gdbm_errno' is treated as thread specific data, and functions of Hovel are reentrant. In that case, they are thread-safe as long as a handle is not accessed by threads at the same time, on the assumption that `errno', `malloc', and so on are thread-safe.


Commands for Hovel

Hovel has the following command line interfaces.

The command `hvmgr' is a utility for debugging Hovel and its applications. It features editing and checking of a database. It can be used for database applications with shell scripts. This command is used in the following format. `name' specifies a database name. `key' specifies the key of a record. `val' specifies the value of a record.

hvmgr create [-qdbm bnum dnum] [-s] name
Create a database file.
hvmgr store [-qdbm] [-kx] [-vx|-vf] [-insert] name key val
Store a record with a key and a value.
hvmgr delete [-qdbm] [-kx] name key
Delete a record with a key.
hvmgr fetch [-qdbm] [-kx] [-ox] [-n] name key
Retrieve a record with a key and output to the standard output.
hvmgr list [-qdbm] [-ox] name
List all keys and values delimited with tab and line-feed to the standard output.
hvmgr optimize [-qdbm] name
Optimize a database.

Options feature the following.

  • -qdbm [bnum dnum] : use `gdbm_open2' to open the database. `bnum' specifies the number of the elements of the bucket array. `dnum' specifies the number of division of the database.
  • -s : make the file sparse.
  • -kx : treat `key' as a binary expression of hexadecimal notation.
  • -vx : treat `val' as a binary expression of hexadecimal notation.
  • -vf : read the value from a file specified with `val'.
  • -insert : specify the storing mode for `GDBM_INSERT'.
  • -ox : treat the output as a binary expression of hexadecimal notation.
  • -n : do not output the trailing newline.

This command returns 0 on success, another on failure.

The command `hvtest' is a utility for facility test and performance test. Check a database generated by the command or measure the execution time of the command. This command is used in the following format. `name' specifies a database name. `rnum' specifies the number of records.

hvtest write [-qdbm] [-s] name rnum
Store records with keys of 8 bytes. They changes as `00000001', `00000002'...
hvtest read [-qdbm] name rnum
Retrieve records of the database above.

Options feature the following.

  • -qdbm : use `gdbm_open2' and open the handle as Curia.
  • -s : make the file sparse.

This command returns 0 on success, another on failure.


Cabin: Utility API

Overview

Cabin is the utility API which provides memory allocating functions, sorting functions, extensible datum, array list, hash map, heap array, and so on for handling records easily on memory. This API features also parsing MIME, CSV, and XML, and features various types of encoding and decoding.

In order to use Cabin, you should include `cabin.h' and `stdlib.h' in the source files. Usually, the following description will be near the beginning of a source file.

#include <cabin.h>
#include <stdlib.h>

A pointer to `CBDATUM' is used as a handle of an extensible datum. A datum handle is opened with the function `cbdatumopen' and closed with `cbdatumclose'. A pointer to `CBLIST' is used as a handle of an array list. A list handle is opened with the function `cblistopen' and closed with `cblistclose'. A pointer to `CBMAP' is used as a handle of a hash map. A map handle is opened with the function `cbmapopen' and closed with `cbmapclose'. A pointer to `CBHEAP' is used as a handle of a heap array. A heap handle is opened with the function `cbheapopen' and closed with `cbheapclose'. You should not refer directly to any member of each handles.

API

The external variable `cbfatalfunc' is the pointer to call back function for handling a fatal error.

extern void (*cbfatalfunc)(const char *);
The argument specifies the error message. The initial value of this variable is `NULL'. If the value is `NULL', the default function is called when a fatal error occurs. A fatal error occurs when memory allocation is failed.

The function `cbmalloc' is used in order to allocate a region on memory.

void *cbmalloc(size_t size);
`size' specifies the size of the region. The return value is the pointer to the allocated region. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.

The function `cbrealloc' is used in order to re-allocate a region on memory.

void *cbrealloc(void *ptr, size_t size);
`ptr' specifies the pointer to a region. `size' specifies the size of the region. The return value is the pointer to the re-allocated region. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.

The function `cbmemdup' is used in order to duplicate a region on memory.

char *cbmemdup(const char *ptr, int size);
`ptr' specifies the pointer to a region. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. The return value is the pointer to the allocated region of the duplicate. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.

The function `cbfree' is used in order to free a region on memory.

void cbfree(void *ptr);
`ptr' specifies the pointer to a region. If it is `NULL', this function has no effect. Although this function is just a wrapper of `free' call, this is useful in applications using another package of the `malloc' series.

The function `cbglobalgc' is used in order to register the pointer or handle of an object to the global garbage collector.

void cbglobalgc(void *ptr, void (*func)(void *));
`ptr' specifies the pointer or handle of an object. `func' specifies the pointer to a function to release resources of the object. Its argument is the pointer or handle of the object to release. This function assures that resources of an object are released when the process exits normally by returning from the `main' function or calling the `exit' function.

The function `cbggcsweep' is used in order to exercise the global garbage collector explicitly.

void cbggcsweep(void);
Note that you should not use objects registered to the global garbage collector any longer after calling this function. Because the global garbage collector is initialized and you can register new objects into it.

The function `cbvmemavail' is used in order to check availability of allocation of the virtual memory.

int cbvmemavail(size_t size);
`size' specifies the size of region to be allocated newly. The return value is true if allocation should be success, or false if not.

The function `cbisort' is used in order to sort an array using insert sort.

void cbisort(void *base, int nmemb, int size, int(*compar)(const void *, const void *));
`base' specifies the pointer to an array. `nmemb' specifies the number of elements of the array. `size' specifies the size of each element. `compar' specifies the pointer to comparing function. The two arguments specify the pointers of elements. The comparing function should returns positive if the former is big, negative if the latter is big, 0 if both are equal. Insert sort is useful only if most elements have been sorted already.

The function `cbssort' is used in order to sort an array using shell sort.

void cbssort(void *base, int nmemb, int size, int(*compar)(const void *, const void *));
`base' specifies the pointer to an array. `nmemb' specifies the number of elements of the array. `size' specifies the size of each element. `compar' specifies the pointer to comparing function. The two arguments specify the pointers of elements. The comparing function should returns positive if the former is big, negative if the latter is big, 0 if both are equal. If most elements have been sorted, shell sort may be faster than heap sort or quick sort.

The function `cbhsort' is used in order to sort an array using heap sort.

void cbhsort(void *base, int nmemb, int size, int(*compar)(const void *, const void *));
`base' specifies the pointer to an array. `nmemb' specifies the number of elements of the array. `size' specifies the size of each element. `compar' specifies the pointer to comparing function. The two arguments specify the pointers of elements. The comparing function should returns positive if the former is big, negative if the latter is big, 0 if both are equal. Although heap sort is robust against bias of input, quick sort is faster in most cases.

The function `cbqsort' is used in order to sort an array using quick sort.

void cbqsort(void *base, int nmemb, int size, int(*compar)(const void *, const void *));
`base' specifies the pointer to an array. `nmemb' specifies the number of elements of the array. `size' specifies the size of each element. `compar' specifies the pointer to comparing function. The two arguments specify the pointers of elements. The comparing function should returns positive if the former is big, negative if the latter is big, 0 if both are equal. Being sensitive to bias of input, quick sort is the fastest sorting algorithm.

The function `cbstricmp' is used in order to compare two strings with case insensitive evaluation.

int cbstricmp(const char *astr, const char *bstr);
`astr' specifies the pointer of one string. `astr' specifies the pointer of the other string. The return value is positive if the former is big, negative if the latter is big, 0 if both are equivalent. Upper cases and lower cases of alphabets in ASCII code are not distinguished.

The function `cbstrfwmatch' is used in order to check whether a string begins with a key.

int cbstrfwmatch(const char *str, const char *key);
`str' specifies the pointer of a target string. `key' specifies the pointer of a forward matching key string. The return value is true if the target string begins with the key, else, it is false.

The function `cbstrfwimatch' is used in order to check whether a string begins with a key, with case insensitive evaluation.

int cbstrfwimatch(const char *str, const char *key);
`str' specifies the pointer of a target string. `key' specifies the pointer of a forward matching key string. The return value is true if the target string begins with the key, else, it is false. Upper cases and lower cases of alphabets in ASCII code are not distinguished.

The function `cbstrbwmatch' is used in order to check whether a string ends with a key.

int cbstrbwmatch(const char *str, const char *key);
`str' specifies the pointer of a target string. `key' specifies the pointer of a backward matching key string. The return value is true if the target string ends with the key, else, it is false.

The function `cbstrbwimatch' is used in order to check whether a string ends with a key, with case insensitive evaluation.

int cbstrbwimatch(const char *str, const char *key);
`str' specifies the pointer of a target string. `key' specifies the pointer of a backward matching key string. The return value is true if the target string ends with the key, else, it is false. Upper cases and lower cases of alphabets in ASCII code are not distinguished.

The function `cbstrstrkmp' is used in order to locate a substring in a string using KMP method.

char *cbstrstrkmp(const char *haystack, const char *needle);
`haystack' specifies the pointer of a target string. `needle' specifies the pointer of a substring to be found. The return value is the pointer to the beginning of the substring or `NULL' if the substring is not found. In most cases, `strstr' as a built-in function of the compiler is faster than this function.

The function `cbstrstrkmp' is used in order to locate a substring in a string using BM method.

char *cbstrstrbm(const char *haystack, const char *needle);
`haystack' specifies the pointer of a target string. `needle' specifies the pointer of a substring to be found. The return value is the pointer to the beginning of the substring or `NULL' if the substring is not found. In most cases, `strstr' as a built-in function of the compiler is faster than this function.

The function `cbstrtoupper' is used in order to convert the letters of a string to upper case.

char *cbstrtoupper(char *str);
`str' specifies the pointer of a string to convert. The return value is the pointer to the string.

The function `cbstrtolower' is used in order to convert the letters of a string to lower case.

char *cbstrtolower(char *str);
`str' specifies the pointer of a string to convert. The return value is the pointer to the string.

The function `cbstrtrim' is used in order to cut space characters at head or tail of a string.

char *cbstrtrim(char *str);
`str' specifies the pointer of a string to convert. The return value is the pointer to the string.

The function `cbstrsqzspc' is used in order to squeeze space characters in a string and trim it.

char *cbstrsqzspc(char *str);
`str' specifies the pointer of a string to convert. The return value is the pointer to the string.

The function `cbstrcountutf' is used in order to count the number of characters in a string of UTF-8.

int cbstrcountutf(const char *str);
`str' specifies the pointer of a string of UTF-8. The return value is the number of characters in the string.

The function `cbstrcututf' is used in order to cut a string of UTF-8 at the specified number of characters.

char *cbstrcututf(char *str, int num);
`str' specifies the pointer of a string of UTF-8. `num' specifies the number of characters to be kept. The return value is the pointer to the string.

The function `cbdatumopen' is used in order to get a datum handle.

CBDATUM *cbdatumopen(const char *ptr, int size);
`ptr' specifies the pointer to the region of the initial content. If it is `NULL', an empty datum is created. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. The return value is a datum handle.

The function `cbdatumdup' is used in order to copy a datum.

CBDATUM *cbdatumdup(const CBDATUM *datum);
`datum' specifies a datum handle. The return value is a new datum handle.

The function `cbdatumclose' is used in order to free a datum handle.

void cbdatumclose(CBDATUM *datum);
`datum' specifies a datum handle. Because the region of a closed handle is released, it becomes impossible to use the handle.

The function `cbdatumcat' is used in order to concatenate a datum and a region.

void cbdatumcat(CBDATUM *datum, const char *ptr, int size);
`datum' specifies a datum handle. `ptr' specifies the pointer to the region to be appended. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'.

The function `cbdatumptr' is used in order to get the pointer of the region of a datum.

const char *cbdatumptr(const CBDATUM *datum);
`datum' specifies a datum handle. The return value is the pointer of the region of a datum. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string.

The function `cbdatumsize' is used in order to get the size of the region of a datum.

int cbdatumsize(const CBDATUM *datum);
`datum' specifies a datum handle. The return value is the size of the region of a datum.

The function `cbdatumsetsize' is used in order to change the size of the region of a datum.

void cbdatumsetsize(CBDATUM *datum, int size);
`datum' specifies a datum handle. `size' specifies the new size of the region. If the new size is bigger than the one of old, the surplus region is filled with zero codes.

The function `cbdatumprintf' is used in order to perform formatted output into a datum.

void cbdatumprintf(CBDATUM *datum, const char *format, ...);
`format' specifies a printf-like format string. The conversion character `%' can be used with such flag characters as `s', `d', `o', `u', `x', `X', `c', `e', `E', `f', `g', `G', `@', `?', `:', `%'. `@' works as with `s' but escapes meta characters of XML. `?' works as with `s' but escapes meta characters of URL. `:' works as with `s' but performs MIME encoding as UTF-8. The other conversion character work as with each original.

The function `cbdatumtomalloc' is used in order to convert a datum to an allocated region.

char *cbdatumtomalloc(CBDATUM *datum, int *sp);
`datum' specifies a datum handle. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. The return value is the pointer to the region of the datum. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. Because the region of the original datum is released, it should not be released again.

The function `cblistopen' is used in order to get a list handle.

CBLIST *cblistopen(void);
The return value is a list handle.

The function `cblistdup' is used in order to copy a list.

CBLIST *cblistdup(const CBLIST *list);
`list' specifies a list handle. The return value is a new list handle.

The function `cblistclose' is used in order to close a list handle.

void cblistclose(CBLIST *list);
`list' specifies a list handle. Because the region of a closed handle is released, it becomes impossible to use the handle.

The function `cblistnum' is used in order to get the number of elements of a list.

int cblistnum(const CBLIST *list);
`list' specifies a list handle. The return value is the number of elements of the list.

The function `cblistval' is used in order to get the pointer to the region of an element of a list.

const char *cblistval(const CBLIST *list, int index, int *sp);
`list' specifies a list handle. `index' specifies the index of an element. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. The return value is the pointer to the region of the element. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. If `index' is equal to or more than the number of elements, the return value is `NULL'.

The function `cblistpush' is used in order to add an element at the end of a list.

void cblistpush(CBLIST *list, const char *ptr, int size);
`list' specifies a list handle. `ptr' specifies the pointer to the region of an element. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'.

The function `cblistpop' is used in order to remove an element of the end of a list.

char *cblistpop(CBLIST *list, int *sp);
`list' specifies a list handle. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. The return value is the pointer to the region of the value. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. If the list is empty, the return value is `NULL'.

The function `cblistunshift' is used in order to add an element at the top of a list.

void cblistunshift(CBLIST *list, const char *ptr, int size);
`list' specifies a list handle. `ptr' specifies the pointer to the region of an element. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'.

The function `cblistshift' is used in order to remove an element of the top of a list.

char *cblistshift(CBLIST *list, int *sp);
`list' specifies a list handle. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. The return value is the pointer to the region of the value. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. If the list is empty, the return value is `NULL'.

The function `cblistinsert' is used in order to add an element at the specified location of a list.

void cblistinsert(CBLIST *list, int index, const char *ptr, int size);
`list' specifies a list handle. `index' specifies the index of an element. `ptr' specifies the pointer to the region of the element. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'.

The function `cblistremove' is used in order to remove an element at the specified location of a list.

char *cblistremove(CBLIST *list, int index, int *sp);
`list' specifies a list handle. `index' specifies the index of an element. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. The return value is the pointer to the region of the value. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. If `index' is equal to or more than the number of elements, no element is removed and the return value is `NULL'.

The function `cblistover' is used in order to overwrite an element at the specified location of a list.

void cblistover(CBLIST *list, int index, const char *ptr, int size);
`list' specifies a list handle. `index' specifies the index of an element. `ptr' specifies the pointer to the region of the new content. `size' specifies the size of the new content. If it is negative, the size is assigned with `strlen(ptr)'. If `index' is equal to or more than the number of elements, this function has no effect.

The function `cblistsort' is used in order to sort elements of a list in lexical order.

void cblistsort(CBLIST *list);
`list' specifies a list handle. Quick sort is used for sorting.

The function `cblistlsearch' is used in order to search a list for an element using liner search.

int cblistlsearch(const CBLIST *list, const char *ptr, int size);
`list' specifies a list handle. `ptr' specifies the pointer to the region of a key. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. The return value is the index of a corresponding element or -1 if there is no corresponding element. If two or more elements corresponds, the former returns.

The function `cblistbsearch' is used in order to search a list for an element using binary search.

int cblistbsearch(const CBLIST *list, const char *ptr, int size);
`list' specifies a list handle. It should be sorted in lexical order. `ptr' specifies the pointer to the region of a key. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. The return value is the index of a corresponding element or -1 if there is no corresponding element. If two or more elements corresponds, which returns is not defined.

The function `cblistdump' is used in order to serialize a list into a byte array.

char *cblistdump(const CBLIST *list, int *sp);
`list' specifies a list handle. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. The return value is the pointer to the region of the result serial region. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.

The function `cblistload' is used in order to redintegrate a serialized list.

CBLIST *cblistload(const char *ptr, int size);
`ptr' specifies the pointer to a byte array. `size' specifies the size of the region. The return value is a new list handle.

The function `cbmapopen' is used in order to get a map handle.

CBMAP *cbmapopen(void);
The return value is a map handle.

The function `cbmapdup' is used in order to copy a map.

CBMAP *cbmapdup(CBMAP *map);
`map' specifies a map handle. The return value is a new map handle. The iterator of the source map is initialized.

The function `cbmapclose' is used in order to close a map handle.

void cbmapclose(CBMAP *map);
`map' specifies a map handle. Because the region of a closed handle is released, it becomes impossible to use the handle.

The function `cbmapput' is used in order to store a record into a map.

int cbmapput(CBMAP *map, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int over);
`map' specifies a map handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `vbuf' specifies the pointer to the region of a value. `vsiz' specifies the size of the region of the value. If it is negative, the size is assigned with `strlen(vbuf)'. `over' specifies whether the value of the duplicated record is overwritten or not. If `over' is false and the key duplicated, the return value is false, else, it is true.

The function `cbmapputcat' is used in order to concatenate a value at the end of the value of the existing record.

void cbmapputcat(CBMAP *map, const char *kbuf, int ksiz, const char *vbuf, int vsiz);
`map' specifies a map handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `vbuf' specifies the pointer to the region of a value. `vsiz' specifies the size of the region of the value. If it is negative, the size is assigned with `strlen(vbuf)'. If there is no corresponding record, a new record is created.

The function `cbmapout' is used in order to delete a record of a map.

int cbmapout(CBMAP *map, const char *kbuf, int ksiz);
`map' specifies a map handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. If successful, the return value is true. False is returned when no record corresponds to the specified key.

The function `cbmapget' is used in order to retrieve a record of a map.

const char *cbmapget(const CBMAP *map, const char *kbuf, int ksiz, int *sp);
`map' specifies a map handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the region of the value of the corresponding record. `NULL' is returned when no record corresponds. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string.

The function `cbmapmove' is used in order to move a record to the edge of a map.

int cbmapmove(CBMAP *map, const char *kbuf, int ksiz, int head);
`map' specifies a map handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `head' specifies the destination which is head if it is true or tail if else. If successful, the return value is true. False is returned when no record corresponds to the specified key.

The function `cbmapiterinit' is used in order to initialize the iterator of a map.

void cbmapiterinit(CBMAP *map);
`map' specifies a map handle. The iterator is used in order to access the key of every record stored in a map.

The function `cbmapiternext' is used in order to get the next key of the iterator of a map.

const char *cbmapiternext(CBMAP *map, int *sp);
`map' specifies a map handle. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the region of the next key, else, it is `NULL'. `NULL' is returned when no record is to be get out of the iterator. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. The order of iteration is assured to be the same of the one of storing.

The function `cbmapiterval' is used in order to get the value binded to the key fetched from the iterator of a map.

const char *cbmapiterval(const char *kbuf, int *sp);
`kbuf' specifies the pointer to the region of a iteration key. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. The return value is the pointer to the region of the value of the corresponding record. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string.

The function `cbmaprnum' is used in order to get the number of the records stored in a map.

int cbmaprnum(const CBMAP *map);
`map' specifies a map handle. The return value is the number of the records stored in the map.

The function `cbmapkeys' is used in order to get the list handle contains all keys in a map.

CBLIST *cbmapkeys(CBMAP *map);
`map' specifies a map handle. The return value is the list handle contains all keys in the map. Because the handle of the return value is opened with the function `cblistopen', it should be closed with the function `cblistclose' if it is no longer in use.

The function `cbmapvals' is used in order to get the list handle contains all values in a map.

CBLIST *cbmapvals(CBMAP *map);
`map' specifies a map handle. The return value is the list handle contains all values in the map. Because the handle of the return value is opened with the function `cblistopen', it should be closed with the function `cblistclose' if it is no longer in use.

The function `cbmapdump' is used in order to serialize a map into a byte array.

char *cbmapdump(const CBMAP *map, int *sp);
`map' specifies a map handle. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. The return value is the pointer to the region of the result serial region. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.

The function `cbmapload' is used in order to redintegrate a serialized map.

CBMAP *cbmapload(const char *ptr, int size);
`ptr' specifies the pointer to a byte array. `size' specifies the size of the region. The return value is a new map handle.

The function `cbmaploadone' is used in order to extract a record from a serialized map.

char *cbmaploadone(const char *ptr, int size, const char *kbuf, int ksiz, int *sp);
`ptr' specifies the pointer to a byte array. `size' specifies the size of the region. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the region of the value of the corresponding record. `NULL' is returned when no record corresponds. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string.

The function `cbheapopen' is used in order to get a heap handle.

CBHEAP *cbheapopen(int size, int max, int(*compar)(const void *, const void *));
`size' specifies the size of each record. `max' specifies the maximum number of records in the heap. `compar' specifies the pointer to comparing function. The two arguments specify the pointers of records. The comparing function should returns positive if the former is big, negative if the latter is big, 0 if both are equal. The return value is a heap handle.

The function `cbheapdup' is used in order to copy a heap.

CBHEAP *cbheapdup(CBHEAP *heap);
`heap' specifies a heap handle. The return value is a new heap handle.

The function `cbheapclose' is used in order to close a heap handle.

void cbheapclose(CBHEAP *heap);
`heap' specifies a heap handle. Because the region of a closed handle is released, it becomes impossible to use the handle.

The function `cbheapnum' is used in order to get the number of the records stored in a heap.

int cbheapnum(CBHEAP *heap);
`heap' specifies a heap handle. The return value is the number of the records stored in the heap.

The function `cbheapinsert' is used in order to insert a record into a heap.

int cbheapinsert(CBHEAP *heap, const void *ptr);
`heap' specifies a heap handle. `ptr' specifies the pointer to the region of a record. The return value is true if the record is added, else false. If the new record is bigger than the biggest existing regord, the new record is not added. If the new record is added and the number of records exceeds the maximum number, the biggest existing record is removed.

The function `cbheapval' is used in order to get the pointer to the region of a record in a heap.

void *cbheapval(CBHEAP *heap, int index);
`heap' specifies a heap handle. `index' specifies the index of a record. The return value is the pointer to the region of the record. If `index' is equal to or more than the number of records, the return value is `NULL'. Note that records are organized by the nagative order the comparing function.

The function `cbheaptomalloc' is used in order to convert a heap to an allocated region.

void *cbheaptomalloc(CBHEAP *heap, int *np);
`heap' specifies a heap handle. `np' specifies the pointer to a variable to which the number of records of the return value is assigned. If it is `NULL', it is not used. The return value is the pointer to the region of the heap. Records are sorted. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. Because the region of the original heap is released, it should not be released again.

The function `cbsprintf' is used in order to allocate a formatted string on memory.

char *cbsprintf(const char *format, ...);
`format' specifies a printf-like format string. The conversion character `%' can be used with such flag characters as `d', `o', `u', `x', `X', `e', `E', `f', `g', `G', `c', `s', and `%'. Specifiers of the field length and the precision can be put between the conversion characters and the flag characters. The specifiers consist of decimal characters, `.', `+', `-', and the space character. The other arguments are used according to the format string. The return value is the pointer to the allocated region of the result string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.

The function `cbreplace' is used in order to replace some patterns in a string.

char *cbreplace(const char *str, CBMAP *pairs);
`str' specifies the pointer to a source string. `pairs' specifies the handle of a map composed of pairs of replacement. The key of each pair specifies a pattern before replacement and its value specifies the pattern after replacement. The return value is the pointer to the allocated region of the result string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.

The function `cbsplit' is used in order to make a list by splitting a serial datum.

CBLIST *cbsplit(const char *ptr, int size, const char *delim);
`ptr' specifies the pointer to the region of the source content. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. `delim' specifies a string containing delimiting characters. If it is `NULL', zero code is used as a delimiter. The return value is a list handle. If two delimiters are successive, it is assumed that an empty element is between the two. Because the handle of the return value is opened with the function `cblistopen', it should be closed with the function `cblistclose'.

The function `cbreadfile' is used in order to read whole data of a file.

char *cbreadfile(const char *name, int *sp);
`name' specifies the name of a file. If it is `NULL', the standard input is specified. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. The return value is the pointer to the allocated region of the read data. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.

The function `cbwritefile' is used in order to write a serial datum into a file.

int cbwritefile(const char *name, const char *ptr, int size);
`name specifies the name of a file. If it is `NULL', the standard output is specified. `ptr' specifies the pointer to the region of the source content. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. If successful, the return value is true, else, it is false. If the file exists, it is overwritten. Else, a new file is created.

The function `cbreadlines' is used in order to read every line of a file.

CBLIST *cbreadlines(const char *name);
`name' specifies the name of a file. If it is `NULL', the standard input is specified. The return value is a list handle of the lines if successful, else it is NULL. Line separators are cut out. Because the handle of the return value is opened with the function `cblistopen', it should be closed with the function `cblistclose' if it is no longer in use.

The function `cbdirlist' is used in order to read names of files in a directory.

CBLIST *cbdirlist(const char *name);
`name' specifies the name of a directory. The return value is a list handle of names if successful, else it is NULL. Because the handle of the return value is opened with the function `cblistopen', it should be closed with the function `cblistclose' if it is no longer in use.

The function `cbfilestat' is used in order to get the status of a file or a directory.

int cbfilestat(const char *name, int *isdirp, int *sizep, int *mtimep);
`name' specifies the name of a file or a directory. `dirp' specifies the pointer to a variable to which whether the file is a directory is assigned. If it is `NULL', it is not used. `sizep' specifies the pointer to a variable to which the size of the file is assigned. If it is `NULL', it is not used. `mtimep' specifies the pointer to a variable to which the last modified time of the file is assigned. If it is `NULL', it is not used. If successful, the return value is true, else, false. False is returned when the file does not exist or the permission is denied.

The function `cbremove' is used in order to remove a file or a directory and its sub ones recursively.

int cbremove(const char *name);
`name' specifies the name of a file or a directory. If successful, the return value is true, else, false. False is returned when the file does not exist or the permission is denied.

The function `cburlbreak' is used in order to break up a URL into elements.

CBMAP *cburlbreak(const char *str);
`str' specifies the pointer to a string of URL. The return value is a map handle. Each key of the map is the name of an element. The key "self" specifies the URL itself. The key "scheme" specifies the scheme. The key "host" specifies the host of the server. The key "port" specifies the port number of the server. The key "authority" specifies the authority information. The key "path" specifies the path of the resource. The key "file" specifies the file name without the directory section. The key "query" specifies the query string. The key "fragment" specifies the fragment string. Supported schema are HTTP, HTTPS, FTP, and FILE. Absolute URL and relative URL are supported. Because the handle of the return value is opened with the function `cbmapopen', it should be closed with the function `cbmapclose' if it is no longer in use.

The runction `cburlresolve' is used in order to resolve a relative URL with another absolute URL.

char *cburlresolve(const char *base, const char *target);
`base' specifies an absolute URL of a base location. `target' specifies a URL to be resolved. The return value is a resolved URL. If the target URL is relative, a new URL of relative location from the base location is returned. Else, a copy of the target URL is returned. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.

The function `cburlencode' is used in order to encode a serial object with URL encoding.

char *cburlencode(const char *ptr, int size);
`ptr' specifies the pointer to a region. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. The return value is the pointer to the result string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.

The function `cburldecode' is used in order to decode a string encoded with URL encoding.

char *cburldecode(const char *str, int *sp);
`str' specifies the pointer to a source string. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. The return value is the pointer to the region of the result. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.

The function `cbbaseencode' is used in order to encode a serial object with Base64 encoding.

char *cbbaseencode(const char *ptr, int size);
`ptr' specifies the pointer to a region. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. The return value is the pointer to the result string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.

The function `cbbasedecode' is used in order to decode a string encoded with Base64 encoding.

char *cbbasedecode(const char *str, int *sp);
`str' specifies the pointer to a source string. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. The return value is the pointer to the region of the result. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.

The function `cbquoteencode' is used in order to encode a serial object with quoted-printable encoding.

char *cbquoteencode(const char *ptr, int size);
`ptr' specifies the pointer to a region. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. The return value is the pointer to the result string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.

The function `cbquotedecode' is used in order to decode a string encoded with quoted-printable encoding.

char *cbquotedecode(const char *str, int *sp);
`str' specifies the pointer to a source string. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. The return value is the pointer to the region of the result. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.

The function `cbmimebreak' is used in order to split a string of MIME into headers and the body.

char *cbmimebreak(const char *ptr, int size, CBMAP *attrs, int *sp);
`ptr' specifies the pointer to the region of MIME data. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. `attrs' specifies a map handle to store attributes. If it is `NULL', it is not used. Each key of the map is an attribute name uncapitalized. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. The return value is the pointer of the body data. If the content type is defined, the attribute map has the key "TYPE" specifying the type. If the character encoding is defined, the key "CHARSET" specifies the encoding name. If the boundary string of multipart is defined, the key "BOUNDARY" specifies the string. If the content disposition is defined, the key "DISPOSITION" specifies the direction. If the file name is defined, the key "FILENAME" specifies the name. If the attribute name is defined, the key "NAME" specifies the name. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.

The function `cbmimeparts' is used in order to split multipart data of MIME into its parts.

CBLIST *cbmimeparts(const char *ptr, int size, const char *boundary);
`ptr' specifies the pointer to the region of multipart data of MIME. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. `boundary' specifies the pointer to the region of the boundary string. The return value is a list handle. Each element of the list is the string of a part. Because the handle of the return value is opened with the function `cblistopen', it should be closed with the function `cblistclose' if it is no longer in use.

The function `cbmimeencode' is used in order to encode a string with MIME encoding.

char *cbmimeencode(const char *str, const char *encname, int base);
`str' specifies the pointer to a string. `encname' specifies a string of the name of the character encoding. The return value is the pointer to the result string. `base' specifies whether to use Base64 encoding. If it is false, quoted-printable is used. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.

The function `cbmimedecode' is used in order to decode a string encoded with MIME encoding.

char *cbmimedecode(const char *str, char *enp);
`str' specifies the pointer to an encoded string. `enp' specifies the pointer to a region into which the name of encoding is written. If it is `NULL', it is not used. The size of the buffer should be equal to or more than 32 bytes. The return value is the pointer to the result string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.

The function `cbcsvrows' is used in order to split a string of CSV into rows.

CBLIST *cbcsvrows(const char *str);
`str' specifies the pointer to the region of an CSV string. The return value is a list handle. Each element of the list is a string of a row. Because the handle of the return value is opened with the function `cblistopen', it should be closed with the function `cblistclose' if it is no longer in use. The character encoding of the input string should be US-ASCII, UTF-8, ISO-8859-*, EUC-*, or Shift_JIS. Being compatible with MS-Excel, these functions for CSV can handle cells including such meta characters as comma, between double quotation marks.

The function `cbcsvcells' is used in order to split the string of a row of CSV into cells.

CBLIST *cbcsvcells(const char *str);
`str' specifies the pointer to the region of a row of CSV. The return value is a list handle. Each element of the list is the unescaped string of a cell of the row. Because the handle of the return value is opened with the function `cblistopen', it should be closed with the function `cblistclose' if it is no longer in use.

The function `cbcsvescape' is used in order to escape a string with the meta characters of CSV.

char *cbcsvescape(const char *str);
`str' specifies the pointer to the region of a string. The return value is the pointer to the escaped string sanitized of meta characters. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.

The function `cbcsvunescape' is used in order to unescape a string with the escaped meta characters of CSV.

char *cbcsvunescape(const char *str);
`str' specifies the pointer to the region of a string with meta characters. The return value is the pointer to the unescaped string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.

The function `cbxmlbreak' is used in order to split a string of XML into tags and text sections.

CBLIST *cbxmlbreak(const char *str, int cr);
`str' specifies the pointer to the region of an XML string. `cr' specifies whether to remove comments. The return value is a list handle. Each element of the list is the string of a tag or a text section. Because the handle of the return value is opened with the function `cblistopen', it should be closed with the function `cblistclose' if it is no longer in use. The character encoding of the input string should be US-ASCII, UTF-8, ISO-8859-*, EUC-*, or Shift_JIS. Because these functions for XML are not XML parser with validation check, it can handle also HTML and SGML.

The function `cbxmlattrs' is used in order to get the map of attributes of an XML tag.

CBMAP *cbxmlattrs(const char *str);
`str' specifies the pointer to the region of a tag string. The return value is a map handle. Each key of the map is the name of an attribute. Each value is unescaped. You can get the name of the tag with the key of an empty string. Because the handle of the return value is opened with the function `cbmapopen', it should be closed with the function `cbmapclose' if it is no longer in use.

The function `cbxmlescape' is used in order to escape a string with the meta characters of XML.

char *cbxmlescape(const char *str);
`str' specifies the pointer to the region of a string. The return value is the pointer to the escaped string sanitized of meta characters. This function converts only `&', `<', `>', and `"'. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.

The function `cbxmlunescape' is used in order to unescape a string with the entity references of XML.

char *cbxmlunescape(const char *str);
`str' specifies the pointer to the region of a string. The return value is the pointer to the unescaped string. This function restores only `&amp;', `&lt;', `&gt;', and `&quot;'. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.

The function `cbdeflate' is used in order to compress a serial object with ZLIB.

char *cbdeflate(const char *ptr, int size, int *sp);
`ptr' specifies the pointer to a region. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If successful, the return value is the pointer to the result object, else, it is `NULL'. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. This function is available only if QDBM was built with ZLIB enabled.

The function `cbinflate' is used in order to decompress a serial object compressed with ZLIB.

char *cbinflate(const char *ptr, int size, int *sp);
`ptr' specifies the pointer to a region. `size' specifies the size of the region. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the result object, else, it is `NULL'. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. This function is available only if QDBM was built with ZLIB enabled.

The function `cbgzencode' is used in order to compress a serial object with GZIP.

char *cbgzencode(const char *ptr, int size, int *sp);
`ptr' specifies the pointer to a region. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If successful, the return value is the pointer to the result object, else, it is `NULL'. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. This function is available only if QDBM was built with ZLIB enabled.

The function `cbgzdecode' is used in order to decompress a serial object compressed with GZIP.

char *cbgzdecode(const char *ptr, int size, int *sp);
`ptr' specifies the pointer to a region. `size' specifies the size of the region. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the result object, else, it is `NULL'. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. This function is available only if QDBM was built with ZLIB enabled.

The function `cbgetcrc' is used in order to get the CRC32 checksum of a serial object.

unsigned int cbgetcrc(const char *ptr, int size);
`ptr' specifies the pointer to a region. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. The return value is the CRC32 checksum of the object. This function is available only if QDBM was built with ZLIB enabled.

The function `cblzoencode' is used in order to compress a serial object with LZO.

char *cblzoencode(const char *ptr, int size, int *sp);
`ptr' specifies the pointer to a region. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If successful, the return value is the pointer to the result object, else, it is `NULL'. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. This function is available only if QDBM was built with LZO enabled.

The function `cblzodecode' is used in order to decompress a serial object compressed with LZO.

char *cblzodecode(const char *ptr, int size, int *sp);
`ptr' specifies the pointer to a region. `size' specifies the size of the region. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the result object, else, it is `NULL'. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. This function is available only if QDBM was built with LZO enabled.

The function `cbbzencode' is used in order to compress a serial object with BZIP2.

char *cbbzencode(const char *ptr, int size, int *sp);
`ptr' specifies the pointer to a region. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If successful, the return value is the pointer to the result object, else, it is `NULL'. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. This function is available only if QDBM was built with BZIP2 enabled.

The function `cbbzdecode' is used in order to decompress a serial object compressed with BZIP2.

char *cbbzdecode(const char *ptr, int size, int *sp);
`ptr' specifies the pointer to a region. `size' specifies the size of the region. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the result object, else, it is `NULL'. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. This function is available only if QDBM was built with BZIP2 enabled.

The function `cbiconv' is used in order to convert the character encoding of a string.

char *cbiconv(const char *ptr, int size, const char *icode, const char *ocode, int *sp, int *mp);
`ptr' specifies the pointer to a region. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. `icode' specifies the name of encoding of the input string. `ocode' specifies the name of encoding of the output string. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. `mp' specifies the pointer to a variable to which the number of missing characters by failure of conversion is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the result object, else, it is `NULL'. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. This function is available only if QDBM was built with ICONV enabled.

The function `cbencname' is used in order to detect the encoding of a string automatically.

const char *cbencname(const char *ptr, int size);
`ptr' specifies the pointer to a region. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. The return value is the string of the encoding name of the string. As it stands, US-ASCII, ISO-2022-JP, Shift_JIS, CP932, EUC-JP, UTF-8, UTF-16, UTF-16BE, and UTF-16LE are supported. If none of them matches, ISO-8859-1 is selected. This function is available only if QDBM was built with ICONV enabled.

The function `cbjetlag' is used in order to get the jet lag of the local time in seconds.

int cbjetlag(void);
The return value is the jet lag of the local time in seconds.

The function `cbcalendar' is used in order to get the Gregorian calendar of a time.

void cbcalendar(time_t t, int jl, int *yearp, int *monp, int *dayp, int *hourp, int *minp, int *secp);
`t' specifies a source time. If it is negative, the current time is specified. `jl' specifies the jet lag of a location in seconds. `yearp' specifies the pointer to a variable to which the year is assigned. If it is `NULL', it is not used. `monp' specifies the pointer to a variable to which the month is assigned. If it is `NULL', it is not used. 1 means January and 12 means December. `dayp' specifies the pointer to a variable to which the day of the month is assigned. If it is `NULL', it is not used. `hourp' specifies the pointer to a variable to which the hours is assigned. If it is `NULL', it is not used. `minp' specifies the pointer to a variable to which the minutes is assigned. If it is `NULL', it is not used. `secp' specifies the pointer to a variable to which the seconds is assigned. If it is `NULL', it is not used.

The function `cbdayofweek' is used in order to get the day of week of a date.

int cbdayofweek(int year, int mon, int day);
`year' specifies the year of a date. `mon' specifies the month of the date. `day' specifies the day of the date. The return value is the day of week of the date. 0 means Sunday and 6 means Saturday.

The function `cbdatestrwww' is used in order to get the string for a date in W3CDTF.

char *cbdatestrwww(time_t t, int jl);
`t' specifies a source time. If it is negative, the current time is specified. `jl' specifies the jet lag of a location in seconds. The return value is the string of the date in W3CDTF (YYYY-MM-DDThh:mm:ddTZD). Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.

The function `cbdatestrhttp' is used in order to get the string for a date in RFC 1123 format.

char *cbdatestrhttp(time_t t, int jl);
`t' specifies a source time. If it is negative, the current time is specified. `jl' specifies the jet lag of a location in seconds. The return value is the string of the date in RFC 1123 format (Wdy, DD-Mon-YYYY hh:mm:dd TZD). Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.

The function `cbstrmktime' is used in order to get the time value of a date string in decimal, hexadecimal, W3CDTF, or RFC 822 (1123).

time_t cbstrmktime(const char *str);
`str' specifies a date string in decimal, hexadecimal, W3CDTF, or RFC 822 (1123). The return value is the time value of the date or -1 if the format is invalid. Decimal can be trailed by "s" for in seconds, "m" for in minutes, "h" for in hours, and "d" for in days.

The function `cbproctime' is used in order to get user and system processing times.

void cbproctime(double *usrp, double *sysp);
`usrp' specifies the pointer to a variable to which the user processing time is assigned. If it is `NULL', it is not used. The unit of time is seconds. `sysp' specifies the pointer to a variable to which the system processing time is assigned. If it is `NULL', it is not used. The unit of time is seconds.

The function `cbstdiobin' is used in order to ensure that the standard I/O is binary mode.

void cbstdiobin(void);
This function is useful for applications on dosish file systems.

Examples

The following example is typical use.

#include <cabin.h>
#include <stdlib.h>
#include <stdio.h>

int main(int argc, char **argv){
  CBDATUM *datum;
  CBLIST *list;
  CBMAP *map;
  char *buf1, *buf2;
  int i;

  /* open the datum handle */
  datum = cbdatumopen("123", -1);
  /* concatenate the data */
  cbdatumcat(datum, "abc", -1);
  /* print the datum */
  printf("%s\n", cbdatumptr(datum));
  /* close the datum handle */
  cbdatumclose(datum);

  /* open the list handle */
  list = cblistopen();
  /* add elements into the list */
  cblistpush(list, "apple", -1);
  cblistpush(list, "orange", -1);
  /* print all elements */
  for(i = 0; i < cblistnum(list); i++){
    printf("%s\n", cblistval(list, i, NULL));
  }
  /* close the list handle */
  cblistclose(list);

  /* open the map handle */
  map = cbmapopen();
  /* add records into the map */
  cbmapput(map, "dog", -1, "bowwow", -1, 1);
  cbmapput(map, "cat", -1, "meow", -1, 1);
  /* search for values and print them */
  printf("%s\n", cbmapget(map, "dog", -1, NULL));
  printf("%s\n", cbmapget(map, "cat", -1, NULL));
  /* close the map */
  cbmapclose(map);

  /* Base64 encoding */
  buf1 = cbbaseencode("I miss you.", -1);
  printf("%s\n", buf1);
  /* Base64 decoding */
  buf2 = cbbasedecode(buf1, NULL);
  printf("%s\n", buf2);
  /* release the resources */
  free(buf2);
  free(buf1);

  /* register a plain pointer to the global garbage collector */
  buf1 = cbmemdup("Take it easy.", -1);
  cbglobalgc(buf1, free);
  /* the pointer is available but you don't have to release it */
  printf("%s\n", buf1);
  
  /* register a list to the global garbage collector */
  list = cblistopen();
  cbglobalgc(list, (void (*)(void *))cblistclose);
  /* the handle is available but you don't have to close it */
  cblistpush(list, "Don't hesitate.", -1);
  for(i = 0; i < cblistnum(list); i++){
    printf("%s\n", cblistval(list, i, NULL));    
  }

  return 0;
}

Notes

How to build programs using Cabin is the same as the case of Depot.

gcc -I/usr/local/include -o sample sample.c -L/usr/local/lib -lqdbm

Functions of Cabin except for `cbglobalgc' are thread-safe as long as a handle is not accessed by threads at the same time, on the assumption that `errno', `malloc', and so on are thread-safe.


Commands for Cabin

Cabin has the following command line interfaces.

The command `cbtest' is a utility for facility test and performance test. Measure the execution time of the command. This command is used in the following format. `rnum' specifies the number of records.

cbtest sort [-d] rnum
Perform test of sorting algorithms.
cbtest strstr [-d] rnum
Perform test of string locating algorithms.
cbtest list [-d] rnum
Perform writing test of list.
cbtest map [-d] rnum
Perform writing test of map.
cbtest wicked rnum
Perform updating operations of list and map selected at random.
cbtest misc
Perform test of miscellaneous routines.

Options feature the following.

  • -d : read and show data of the result.

This command returns 0 on success, another on failure.

The command `cbcodec' is a tool to use encoding and decoding features provided by Cabin. This command is used in the following format. `file' specifies a input file. If it is omitted, the standard input is read.

cbcodec url [-d] [-br] [-rs base target] [-l] [-e expr] [file]
Perform URL encoding and its decoding.
cbcodec base [-d] [-l] [-c num] [-e expr] [file]
Perform Base64 encoding and its decoding.
cbcodec quote [-d] [-l] [-c num] [-e expr] [file]
Perform quoted-printable encoding and its decoding.
cbcodec mime [-d] [-hd] [-bd] [-part num] [-l] [-ec code] [-qp] [-dc] [-e expr] [file]
Perform MIME encoding and its decoding.
cbcodec csv [-d] [-t] [-l] [-e expr] [-html] [file]
Process CSV. By default, escape meta characters.
cbcodec xml [-d] [-p] [-l] [-e expr] [-tsv] [file]
Process XML. By default, escape meta characters.
cbcodec zlib [-d] [-gz] [-crc] [file]
Perform deflation and inflation with ZLIB. It is available only if QDBM was built with ZLIB enabled.
cbcodec lzo [-d] [file]
Perform compression and decompression with LZO. It is available only if QDBM was built with LZO enabled.
cbcodec bzip [-d] [file]
Perform compression and decompression with BZIP2. It is available only if QDBM was built with BZIP2 enabled.
cbcodec iconv [-ic code] [-oc code] [-ol ltype] [-cn] [-um] [-wc] [file]
Convert character encoding with ICONV. It is available only if QDBM was built with ICONV enabled.
cbcodec date [-wf] [-rf] [-utc] [str]
Convert a date string specified `str'. By default, UNIX time is output. If `str' is omitted, the current date is dealt.

Options feature the following.

  • -d : perform decoding (unescaping), not encoding (escaping).
  • -br : break up URL into elements.
  • -rs : resolve relative URL.
  • -l : output the tailing newline.
  • -e expr : specify input data directly.
  • -c num : limit the number of columns of the encoded data.
  • -hd : parse MIME and extract headers in TSV format.
  • -bd : parse MIME and extract the body.
  • -part num : parse MIME and extract a part.
  • -ec code : specify the input encoding, which is UTF-8 by default.
  • -qp : use quoted-printable encoding, which is Base64 by default.
  • -dc : output the encoding name instead of the result string when decoding.
  • -t : parse CSV. Convert the data into TSV. Tab and new-line in a cell are deleted.
  • -html : parse CSV. Convert the data into HTML.
  • -p : parse XML. Show tags and text sections with dividing headers.
  • -tsv : parse XML. Show the result in TSV format. Characters of tabs and new-lines are URL-encoded.
  • -gz : use GZIP format.
  • -crc : output the CRC32 checksum as hexadecimal and big endian.
  • -ic code : specify the input encoding, which is detected automatically by default.
  • -oc code : specify the output encoding, which is UTF-8 by default.
  • -ol ltype : convert line feed characters, with `unix'(LF), `dos'(CRLF), and `mac'(CR).
  • -cn : detect the input encoding and show its name.
  • -wc : count the number of characters of the input string of UTF-8.
  • -um : output mappings of UCS-2 characters and C strings of UTF-16BE and UTF-8.
  • -wf : output in W3CDTF format.
  • -rf : output in RFC 1123 format.
  • -utc : output the coordinate universal time.

This command returns 0 on success, another on failure.


Villa: Advanced API

Overview

Villa is the advanced API of QDBM. It provides routines for managing a database file of B+ tree. Each record is stored being sorted in order defined by a user. As for hash databases, retrieving method is provided only as complete accord. However, with Villa, it is possible to retrieve records specified by range. Cursor is used in order to access each record in order. It is possible to store records duplicating keys in a database. Moreover, according to the transaction mechanism, you can commit or abort operations of a database in a lump.

Villa is implemented, based on Depot and Cabin. A database file of Villa is actual one of Depot. Although processing speed of retrieving and storing is slower than Depot, the size of a database is smaller.

In order to use Villa, you should include `depot.h', `cabin.h', `villa.h' and `stdlib.h' in the source files. Usually, the following description will be near the beginning of a source file.

#include <depot.h>
#include <cabin.h>
#include <villa.h>
#include <stdlib.h>

A pointer to `VILLA' is used as a database handle. It is like that some file I/O routines of `stdio.h' use a pointer to `FILE'. A database handle is opened with the function `vlopen' and closed with `vlclose'. You should not refer directly to any member of the handle. If a fatal error occurs in a database, any access method via the handle except `vlclose' will not work and return error status. Although a process is allowed to use multiple database handles at the same time, handles of the same database file should not be used. Before the cursor is used, it should be initialized by one of `vlcurfirst', `vlcurlast' or `vlcurjump'. Also after storing or deleting a record with functions except for `vlcurput' and `vlcurout', the cursor should be initialized.

Villa also assign the external variable `dpecode' with the error code. The function `dperrmsg' is used in order to get the message of the error code.

API

You can define a comparing function to specify the order of records. The function should be the following type.

typedef int(*VLCFUNC)(const char *aptr, int asiz, const char *bptr, int bsiz);
`aptr' specifies the pointer to the region of one key. `asiz' specifies the size of the region of one key. `bptr' specifies the pointer to the region of the other key. `bsiz' specifies the size of the region of the other key. The return value is positive if the former is big, negative if the latter is big, 0 if both are equivalent.

The function `vlopen' is used in order to get a database handle.

VILLA *vlopen(const char *name, int omode, VLCFUNC cmp);
`name' specifies the name of a database file. `omode' specifies the connection mode: `VL_OWRITER' as a writer, `VL_OREADER' as a reader. If the mode is `VL_OWRITER', the following may be added by bitwise or: `VL_OCREAT', which means it creates a new database if not exist, `VL_OTRUNC', which means it creates a new database regardless if one exists, `VL_OZCOMP', which means leaves in the database are compressed with ZLIB, `VL_OYCOMP', which means leaves in the database are compressed with LZO, `VL_OXCOMP', which means leaves in the database are compressed with BZIP2. Both of `VL_OREADER' and `VL_OWRITER' can be added to by bitwise or: `VL_ONOLCK', which means it opens a database file without file locking, or `VL_OLCKNB', which means locking is performed without blocking. `cmp' specifies the comparing function: `VL_CMPLEX' comparing keys in lexical order, `VL_CMPINT' comparing keys as objects of `int' in native byte order, `VL_CMPNUM' comparing keys as numbers of big endian, `VL_CMPDEC' comparing keys as decimal strings. Any function based on the declaration of the type `VLCFUNC' can be assigned to the comparing function. The comparing function should be kept same in the life of a database. The return value is the database handle or `NULL' if it is not successful. While connecting as a writer, an exclusive lock is invoked to the database file. While connecting as a reader, a shared lock is invoked to the database file. The thread blocks until the lock is achieved. `VL_OZCOMP', `VL_OYCOMP', and `VL_OXCOMP' are available only if QDBM was built each with ZLIB, LZO, and BZIP2 enabled. If `VL_ONOLCK' is used, the application is responsible for exclusion control.

The function `vlclose' is used in order to close a database handle.

int vlclose(VILLA *villa);
`villa' specifies a database handle. If successful, the return value is true, else, it is false. Because the region of a closed handle is released, it becomes impossible to use the handle. Updating a database is assured to be written when the handle is closed. If a writer opens a database but does not close it appropriately, the database will be broken. If the transaction is activated and not committed, it is aborted.

The function `vlput' is used in order to store a record.

int vlput(VILLA *villa, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int dmode);
`villa' specifies a database handle connected as a writer. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `vbuf' specifies the pointer to the region of a value. `vsiz' specifies the size of the region of the value. If it is negative, the size is assigned with `strlen(vbuf)'. `dmode' specifies behavior when the key overlaps, by the following values: `VL_DOVER', which means the specified value overwrites the existing one, `VL_DKEEP', which means the existing value is kept, `VL_DCAT', which means the specified value is concatenated at the end of the existing value, `VL_DDUP', which means duplication of keys is allowed and the specified value is added as the last one, `VL_DDUPR', which means duplication of keys is allowed and the specified value is added as the first one. If successful, the return value is true, else, it is false. The cursor becomes unavailable due to updating database.

The function `vlout' is used in order to delete a record.

int vlout(VILLA *villa, const char *kbuf, int ksiz);
`villa' specifies a database handle connected as a writer. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. If successful, the return value is true, else, it is false. False is returned when no record corresponds to the specified key. When the key of duplicated records is specified, the first record of the same key is deleted. The cursor becomes unavailable due to updating database.

The function `vlget' is used in order to retrieve a record.

char *vlget(VILLA *villa, const char *kbuf, int ksiz, int *sp);
`villa' specifies a database handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the region of the value of the corresponding record, else, it is `NULL'. `NULL' is returned when no record corresponds to the specified key. When the key of duplicated records is specified, the value of the first record of the same key is selected. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.

The function `vlvsiz' is used in order to get the size of the value of a record.

int vlvsiz(VILLA *villa, const char *kbuf, int ksiz);
`villa' specifies a database handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. If successful, the return value is the size of the value of the corresponding record, else, it is -1. If multiple records correspond, the size of the first is returned.

The function `vlvnum' is used in order to get the number of records corresponding a key.

int vlvnum(VILLA *villa, const char *kbuf, int ksiz);
`villa' specifies a database handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. The return value is the number of corresponding records. If no record corresponds, 0 is returned.

The function `vlputlist' is used in order to store plural records corresponding a key.

int vlputlist(VILLA *villa, const char *kbuf, int ksiz, const CBLIST *vals);
`villa' specifies a database handle connected as a writer. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `vals' specifies a list handle of values. The list should not be empty. If successful, the return value is true, else, it is false. The cursor becomes unavailable due to updating database.

The function `vloutlist' is used in order to delete all records corresponding a key.

int vloutlist(VILLA *villa, const char *kbuf, int ksiz);
`villa' specifies a database handle connected as a writer. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. If successful, the return value is true, else, it is false. False is returned when no record corresponds to the specified key. The cursor becomes unavailable due to updating database.

The function `vlgetlist' is used in order to retrieve values of all records corresponding a key.

CBLIST *vlgetlist(VILLA *villa, const char *kbuf, int ksiz);
`villa' specifies a database handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. If successful, the return value is a list handle of the values of the corresponding records, else, it is `NULL'. `NULL' is returned when no record corresponds to the specified key. Because the handle of the return value is opened with the function `cblistopen', it should be closed with the function `cblistclose' if it is no longer in use.

The function `vlgetcat' is used in order to retrieve concatenated values of all records corresponding a key.

char *vlgetcat(VILLA *villa, const char *kbuf, int ksiz, int *sp);
`villa' specifies a database handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the region of the concatenated values of the corresponding record, else, it is `NULL'. `NULL' is returned when no record corresponds to the specified key. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.

The function `vlcurfirst' is used in order to move the cursor to the first record.

int vlcurfirst(VILLA *villa);
`villa' specifies a database handle. If successful, the return value is true, else, it is false. False is returned if there is no record in the database.

The function `vlcurlast' is used in order to move the cursor to the last record.

int vlcurlast(VILLA *villa);
`villa' specifies a database handle. If successful, the return value is true, else, it is false. False is returned if there is no record in the database.

The function `vlcurprev' is used in order to move the cursor to the previous record.

int vlcurprev(VILLA *villa);
`villa' specifies a database handle. If successful, the return value is true, else, it is false. False is returned if there is no previous record.

The function `vlcurnext' is used in order to move the cursor to the next record.

int vlcurnext(VILLA *villa);
`villa' specifies a database handle. If successful, the return value is true, else, it is false. False is returned if there is no next record.

The function `vlcurjump' is used in order to move the cursor to a position around a record.

int vlcurjump(VILLA *villa, const char *kbuf, int ksiz, int jmode);
`villa' specifies a database handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `jmode' specifies detail adjustment: `VL_JFORWARD', which means that the cursor is set to the first record of the same key and that the cursor is set to the next substitute if completely matching record does not exist, `VL_JBACKWARD', which means that the cursor is set to the last record of the same key and that the cursor is set to the previous substitute if completely matching record does not exist. If successful, the return value is true, else, it is false. False is returned if there is no record corresponding the condition.

The function `vlcurkey' is used in order to get the key of the record where the cursor is.

char *vlcurkey(VILLA *villa, int *sp);
`villa' specifies a database handle. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the region of the key of the corresponding record, else, it is `NULL'. `NULL' is returned when no record corresponds to the cursor. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.

The function `vlcurval' is used in order to get the value of the record where the cursor is.

char *vlcurval(VILLA *villa, int *sp);
`villa' specifies a database handle. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the region of the value of the corresponding record, else, it is `NULL'. `NULL' is returned when no record corresponds to the cursor. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.

The function `vlcurput' is used in order to insert a record around the cursor.

int vlcurput(VILLA *villa, const char *vbuf, int vsiz, int cpmode);
`villa' specifies a database handle connected as a writer. `vbuf' specifies the pointer to the region of a value. `vsiz' specifies the size of the region of the value. If it is negative, the size is assigned with `strlen(vbuf)'. `cpmode' specifies detail adjustment: `VL_CPCURRENT', which means that the value of the current record is overwritten, `VL_CPBEFORE', which means that a new record is inserted before the current record, `VL_CPAFTER', which means that a new record is inserted after the current record. If successful, the return value is true, else, it is false. False is returned when no record corresponds to the cursor. After insertion, the cursor is moved to the inserted record.

The function `vlcurout' is used in order to delete the record where the cursor is.

int vlcurout(VILLA *villa);
`villa' specifies a database handle connected as a writer. If successful, the return value is true, else, it is false. False is returned when no record corresponds to the cursor. After deletion, the cursor is moved to the next record if possible.

The function `vlsettuning' is used in order to set the tuning parameters for performance.

void vlsettuning(VILLA *villa, int lrecmax, int nidxmax, int lcnum, int ncnum);
`villa' specifies a database handle. `lrecmax' specifies the max number of records in a leaf node of B+ tree. If it is not more than 0, the default value is specified. `nidxmax' specifies the max number of indexes in a non-leaf node of B+ tree. If it is not more than 0, the default value is specified. `lcnum' specifies the max number of caching leaf nodes. If it is not more than 0, the default value is specified. `ncnum' specifies the max number of caching non-leaf nodes. If it is not more than 0, the default value is specified. The default setting is equivalent to `vlsettuning(49, 192, 1024, 512)'. Because tuning parameters are not saved in a database, you should specify them every opening a database.

The function `vlsetfbpsiz' is used in order to set the size of the free block pool of a database handle.

int vlsetfbpsiz(VILLA *villa, int size);
`villa' specifies a database handle connected as a writer. `size' specifies the size of the free block pool of a database. If successful, the return value is true, else, it is false. The default size of the free block pool is 256. If the size is greater, the space efficiency of overwriting values is improved with the time efficiency sacrificed.

The function `vlsync' is used in order to synchronize updating contents with the file and the device.

int vlsync(VILLA *villa);
`villa' specifies a database handle connected as a writer. If successful, the return value is true, else, it is false. This function is useful when another process uses the connected database file. This function should not be used while the transaction is activated.

The function `vloptimize' is used in order to optimize a database.

int vloptimize(VILLA *villa);
`villa' specifies a database handle connected as a writer. If successful, the return value is true, else, it is false. In an alternating succession of deleting and storing with overwrite or concatenate, dispensable regions accumulate. This function is useful to do away with them. This function should not be used while the transaction is activated.

The function `vlname' is used in order to get the name of a database.

char *vlname(VILLA *villa);
`villa' specifies a database handle. If successful, the return value is the pointer to the region of the name of the database, else, it is `NULL'. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.

The function `vlfsiz' is used in order to get the size of a database file.

int vlfsiz(VILLA *villa);
`villa' specifies a database handle. If successful, the return value is the size of the database file, else, it is -1. Because of the I/O buffer, the return value may be less than the hard size.

The function `vllnum' is used in order to get the number of the leaf nodes of B+ tree.

int vllnum(VILLA *villa);
`villa' specifies a database handle. If successful, the return value is the number of the leaf nodes, else, it is -1.

The function `vlnnum' is used in order to get the number of the non-leaf nodes of B+ tree.

int vlnnum(VILLA *villa);
`villa' specifies a database handle. If successful, the return value is the number of the non-leaf nodes, else, it is -1.

The function `vlrnum' is used in order to get the number of the records stored in a database.

int vlrnum(VILLA *villa);
`villa' specifies a database handle. If successful, the return value is the number of the records stored in the database, else, it is -1.

The function `vlwritable' is used in order to check whether a database handle is a writer or not.

int vlwritable(VILLA *villa);
`villa' specifies a database handle. The return value is true if the handle is a writer, false if not.

The function `vlfatalerror' is used in order to check whether a database has a fatal error or not.

int vlfatalerror(VILLA *villa);
`villa' specifies a database handle. The return value is true if the database has a fatal error, false if not.

The function `vlinode' is used in order to get the inode number of a database file.

int vlinode(VILLA *villa);
`villa' specifies a database handle. The return value is the inode number of the database file.

The function `vlmtime' is used in order to get the last modified time of a database.

time_t vlmtime(VILLA *villa);
`villa' specifies a database handle. The return value is the last modified time of the database.

The function `vltranbegin' is used in order to begin the transaction.

int vltranbegin(VILLA *villa);
`villa' specifies a database handle connected as a writer. If successful, the return value is true, else, it is false. Because this function does not perform mutual exclusion control in multi-thread, the application is responsible for it. Only one transaction can be activated with a database handle at the same time.

The function `vltrancommit' is used in order to commit the transaction.

int vltrancommit(VILLA *villa);
`villa' specifies a database handle connected as a writer. If successful, the return value is true, else, it is false. Updating a database in the transaction is fixed when it is committed successfully.

The function `vltranabort' is used in order to abort the transaction.

int vltranabort(VILLA *villa);
`villa' specifies a database handle connected as a writer. If successful, the return value is true, else, it is false. Updating a database in the transaction is discarded when it is aborted. The state of the database is rollbacked to before transaction.

The function `vlremove' is used in order to remove a database file.

int vlremove(const char *name);
`name' specifies the name of a database file. If successful, the return value is true, else, it is false.

The function `vlrepair' is used in order to repair a broken database file.

int vlrepair(const char *name, VLCFUNC cmp);
`name' specifies the name of a database file. `cmp' specifies the comparing function of the database file. If successful, the return value is true, else, it is false. There is no guarantee that all records in a repaired database file correspond to the original or expected state.

The function `vlexportdb' is used in order to dump all records as endian independent data.

int vlexportdb(VILLA *villa, const char *name);
`villa' specifies a database handle. `name' specifies the name of an output file. If successful, the return value is true, else, it is false.

The function `vlimportdb' is used in order to load all records from endian independent data.

int vlimportdb(VILLA *villa, const char *name);
`villa' specifies a database handle connected as a writer. The database of the handle must be empty. `name' specifies the name of an input file. If successful, the return value is true, else, it is false.

Examples

The following example stores and retrieves a phone number, using the name as the key.

#include <depot.h>
#include <cabin.h>
#include <villa.h>
#include <stdlib.h>
#include <stdio.h>

#define NAME     "mikio"
#define NUMBER   "000-1234-5678"
#define DBNAME   "book"

int main(int argc, char **argv){
  VILLA *villa;
  char *val;

  /* open the database */
  if(!(villa = vlopen(DBNAME, VL_OWRITER | VL_OCREAT, VL_CMPLEX))){
    fprintf(stderr, "vlopen: %s\n", dperrmsg(dpecode));
    return 1;
  }

  /* store the record */
  if(!vlput(villa, NAME, -1, NUMBER, -1, VL_DOVER)){
    fprintf(stderr, "vlput: %s\n", dperrmsg(dpecode));
  }

  /* retrieve the record */
  if(!(val = vlget(villa, NAME, -1, NULL))){
    fprintf(stderr, "vlget: %s\n", dperrmsg(dpecode));
  } else {
    printf("Name: %s\n", NAME);
    printf("Number: %s\n", val);
    free(val);
  }

  /* close the database */
  if(!vlclose(villa)){
    fprintf(stderr, "vlclose: %s\n", dperrmsg(dpecode));
    return 1;
  }

  return 0;
}

The following example performs forward matching search for strings.

#include <depot.h>
#include <cabin.h>
#include <villa.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#define DBNAME   "words"
#define PREFIX   "apple"

int main(int argc, char **argv){
  VILLA *villa;
  char *key, *val;

  /* open the database */
  if(!(villa = vlopen(DBNAME, VL_OWRITER | VL_OCREAT, VL_CMPLEX))){
    fprintf(stderr, "vlopen: %s\n", dperrmsg(dpecode));
    return 1;
  }

  /* store records */
  if(!vlput(villa, "applet", -1, "little application", -1, VL_DDUP) ||
     !vlput(villa, "aurora", -1, "polar wonderwork", -1, VL_DDUP) ||
     !vlput(villa, "apple", -1, "delicious fruit", -1, VL_DDUP) ||
     !vlput(villa, "amigo", -1, "good friend", -1, VL_DDUP) ||
     !vlput(villa, "apple", -1, "big city", -1, VL_DDUP)){
    fprintf(stderr, "vlput: %s\n", dperrmsg(dpecode));
  }

  /* set the cursor at the top of candidates */
  vlcurjump(villa, PREFIX, -1, VL_JFORWARD);

  /* scan with the cursor */
  while((key = vlcurkey(villa, NULL)) != NULL){
    if(strstr(key, PREFIX) != key){
      free(key);
      break;
    }
    if(!(val = vlcurval(villa, NULL))){
      fprintf(stderr, "vlcurval: %s\n", dperrmsg(dpecode));
      free(key);
      break;
    }
    printf("%s: %s\n", key, val);
    free(val);
    free(key);
    vlcurnext(villa);
  }

  /* close the database */
  if(!vlclose(villa)){
    fprintf(stderr, "vlclose: %s\n", dperrmsg(dpecode));
    return 1;
  }

  return 0;
}

Notes

How to build programs using Villa is the same as the case of Depot.

gcc -I/usr/local/include -o sample sample.c -L/usr/local/lib -lqdbm

If QDBM was built with POSIX thread enabled, the global variable `dpecode' is treated as thread specific data, and functions of Villa are reentrant. In that case, they are thread-safe as long as a handle is not accessed by threads at the same time, on the assumption that `errno', `malloc', and so on are thread-safe.

Vista: Extended Advanced API

Vista is the extended API of Villa. To compensate for the defect that Villa can not handle a file whose size is more than 2GB, Vista does not use Depot but Curia for handling its internal database. While Vista provides data structure and operations of B+ tree as with Villa, its database is realized as a directory.

In order to use Vista, you should include `vista.h' instead of `villa.h'. Because Vista is implemented by overriding symbols of Villa, it can be used as with Villa. That is, Signatures of Villa and Vista is all the same. However, as its adverse effect, modules (compilation unit) using Vista can not use Villa (do not include `villa.h').


Commands for Villa

Villa has the following command line interfaces.

The command `vlmgr' is a utility for debugging Villa and its applications. It features editing and checking of a database. It can be used for database applications with shell scripts. This command is used in the following format. `name' specifies a database name. `key' specifies the key of a record. `val' specifies the value of a record.

vlmgr create [-cz|-cy|-cx] name
Create a database file.
vlmgr put [-kx|-ki] [-vx|-vi|-vf] [-keep|-cat|-dup] name key val
Store a record with a key and a value.
vlmgr out [-l] [-kx|-ki] name key
Delete a record with a key.
vlmgr get [-nl] [-l] [-kx|-ki] [-ox] [-n] name key
Retrieve a record with a key and output it to the standard output.
vlmgr list [-nl] [-k|-v] [-kx|-ki] [-ox] [-top key] [-bot key] [-gt] [-lt] [-max num] [-desc] name
List all keys and values delimited with tab and line-feed to the standard output.
vlmgr optimize name
Optimize a database.
vlmgr inform [-nl] name
Output miscellaneous information to the standard output.
vlmgr remove name
Remove a database file.
vlmgr repair [-ki] name
Repair a broken database file.
vlmgr exportdb [-ki] name file
Dump all records as endian independent data.
vlmgr importdb [-ki] name file
Load all records from endian independent data.
vlmgr version
Output version information of QDBM to the standard output.

Options feature the following.

  • -cz : compress leaves in the database with ZLIB.
  • -cy : compress leaves in the database with LZO.
  • -cx : compress leaves in the database with BZIP2.
  • -l : all records corresponding the key are dealt.
  • -kx : treat `key' as a binary expression of hexadecimal notation.
  • -ki : treat `key' as an integer expression of decimal notation.
  • -vx : treat `val' as a binary expression of hexadecimal notation.
  • -vi : treat `val' as an integer expression of decimal notation.
  • -vf : read the value from a file specified with `val'.
  • -keep : specify the storing mode for `VL_DKEEP'.
  • -cat : specify the storing mode for `VL_DCAT'.
  • -dup : specify the storing mode for `VL_DDUP'.
  • -nl : open the database without file locking.
  • -top key : specify the top key of listing.
  • -bot key : specify the bottom key of listing.
  • -gt : do not include the top key of listing.
  • -lt : do not include the bottom key of listing.
  • -max num : specify the max number of listing.
  • -desc : list in descending order.
  • -ox : treat the output as a binary expression of hexadecimal notation.
  • -n : do not output the tailing newline.
  • -k : output keys only.
  • -v : output values only.

This command returns 0 on success, another on failure. The environment variable `QDBMDBGFD' specifies the file descriptor to output the history of updating the variable `dpecode'.

The command `vltest' is a utility for facility test and performance test. Check a database generated by the command or measure the execution time of the command. This command is used in the following format. `name' specifies a database name. `rnum' specifies the number of the records.

vltest write [-int] [-cz|-cy|-cx] [-tune lrecmax nidxmax lcnum ncnum] [-fbp num] name rnum
Store records with keys of 8 bytes. They change as `00000001', `00000002'...
vltest read [-int] [-vc] name
Retrieve all records of the database above.
vltest rdup [-int] [-cz|-cy|-cx] [-cc] [-tune lrecmax nidxmax lcnum ncnum] [-fbp num] name rnum pnum
Store records with partway duplicated keys using duplicate mode.
vltest combo [-cz|-cy|-cx] name
Perform combination test of various operations.
vltest wicked [-cz|-cy|-cx] name rnum
Perform updating operations selected at random.

Options feature the following.

  • -int : treat keys and values as objects of `int', and use comparing function `VL_CMPINT'.
  • -cz : compress leaves in the database with ZLIB.
  • -cy : compress leaves in the database with LZO.
  • -cx : compress leaves in the database with BZIP2.
  • -vc : refer to volatile cache.
  • -cc : select `VL_DCAT' or `VL_DDUP' at random.
  • -tune lrecmax nidxmax lcnum ncnum : set tuning parameters.
  • -fbp num : set the size of the free block pool.
  • -c : perform comparison test with map of Cabin.

This command returns 0 on success, another on failure. The environment variable `QDBMDBGFD' specifies the file descriptor to output the history of updating the variable `dpecode'.

The command `vltsv' features mutual conversion between a database of Villa and a TSV text. This command is useful when data exchange with another version of QDBM or another DBM, or when data exchange between systems which have different byte orders. This command is used in the following format. `name' specifies a database name. The subcommand `export' reads TSV data from the standard input. The subcommand `import' writes TSV data to the standard output.

vltsv import [-bin] name
Create a database from TSV.
vltsv export [-bin] name
Write TSV data of a database.

Options feature the following.

  • -bin : treat records as Base64 format.

This command returns 0 on success, another on failure.

Commands of Villa realize a simple database system. For example, to make a database to search `/etc/password' by a user name, perform the following command.

cat /etc/passwd | tr ':' '\t' | vltsv import casket

Thus, to retrieve the information of a user `mikio', perform the following command.

vlmgr get casket mikio

It is easy to implement functions upsides with these commands, using the API of Villa.

The command `qmttest' checks multi-thread safety of Depot, Curia, and Villa. This command works with multi threads only if QDBM was built with POSIX thread. This command is used in the following format. `name' specifies the prefix of each database. `rnum' specifies the number of records to be stored in each database. `tnum' specifies the number of threads.

qmttest name rnum tnum
Check multi-thread safety.

This command returns 0 on success, another on failure.


Odeum: Inverted API

Overview

Odeum is the API which handles an inverted index. An inverted index is a data structure to retrieve a list of some documents that include one of words which were extracted from a population of documents. It is easy to realize a full-text search system with an inverted index. Odeum provides an abstract data structure which consists of words and attributes of a document. It is used when an application stores a document into a database and when an application retrieves some documents from a database.

Odeum does not provide methods to extract the text from the original data of a document. It should be implemented by applications. Although Odeum provides utilities to extract words from a text, it is oriented to such languages whose words are separated with space characters as English. If an application handles such languages which need morphological analysis or N-gram analysis as Japanese, or if an application perform more such rarefied analysis of natural languages as stemming, its own analyzing method can be adopted. Result of search is expressed as an array contains elements which are structures composed of the ID number of documents and its score. In order to search with two or more words, Odeum provides utilities of set operations.

Odeum is implemented, based on Curia, Cabin, and Villa. Odeum creates a database with a directory name. Some databases of Curia and Villa are placed in the specified directory. For example, `casket/docs', `casket/index', and `casket/rdocs' are created in the case that a database directory named as `casket'. `docs' is a database directory of Curia. The key of each record is the ID number of a document, and the value is such attributes as URI. `index' is a database directory of Curia. The key of each record is the normalized form of a word, and the value is an array whose element is a pair of the ID number of a document including the word and its score. `rdocs' is a database file of Villa. The key of each record is the URI of a document, and the value is its ID number.

In order to use Odeum, you should include `depot.h', `cabin.h', `odeum.h' and `stdlib.h' in the source files. Usually, the following description will be near the beginning of a source file.

#include <depot.h>
#include <cabin.h>
#include <odeum.h>
#include <stdlib.h>

A pointer to `ODEUM' is used as a database handle. A database handle is opened with the function `odopen' and closed with `odclose'. You should not refer directly to any member of the handle. If a fatal error occurs in a database, any access method via the handle except `odclose' will not work and return error status. Although a process is allowed to use multiple database handles at the same time, handles of the same database file should not be used.

A pointer to `ODDOC' is used as a document handle. A document handle is opened with the function `oddocopen' and closed with `oddocclose'. You should not refer directly to any member of the handle. A document consists of attributes and words. Each word is expressed as a pair of a normalized form and a appearance form.

Odeum also assign the external variable `dpecode' with the error code. The function `dperrmsg' is used in order to get the message of the error code.

API

Structures of `ODPAIR' type is used in order to handle results of search.

typedef struct { int id; int score; } ODPAIR;
`id' specifies the ID number of a document. `score' specifies the score calculated from the number of searching words in the document.

The function `odopen' is used in order to get a database handle.

ODEUM *odopen(const char *name, int omode);
`name' specifies the name of a database directory. `omode' specifies the connection mode: `OD_OWRITER' as a writer, `OD_OREADER' as a reader. If the mode is `OD_OWRITER', the following may be added by bitwise or: `OD_OCREAT', which means it creates a new database if not exist, `OD_OTRUNC', which means it creates a new database regardless if one exists. Both of `OD_OREADER' and `OD_OWRITER' can be added to by bitwise or: `OD_ONOLCK', which means it opens a database directory without file locking, or `OD_OLCKNB', which means locking is performed without blocking. The return value is the database handle or `NULL' if it is not successful. While connecting as a writer, an exclusive lock is invoked to the database directory. While connecting as a reader, a shared lock is invoked to the database directory. The thread blocks until the lock is achieved. If `OD_ONOLCK' is used, the application is responsible for exclusion control.

The function `odclose' is used in order to close a database handle.

int odclose(ODEUM *odeum);
`odeum' specifies a database handle. If successful, the return value is true, else, it is false. Because the region of a closed handle is released, it becomes impossible to use the handle. Updating a database is assured to be written when the handle is closed. If a writer opens a database but does not close it appropriately, the database will be broken.

The function `odput' is used in order to store a document.

int odput(ODEUM *odeum, const ODDOC *doc, int wmax, int over);
`odeum' specifies a database handle connected as a writer. `doc' specifies a document handle. `wmax' specifies the max number of words to be stored in the document database. If it is negative, the number is unlimited. `over' specifies whether the data of the duplicated document is overwritten or not. If it is false and the URI of the document is duplicated, the function returns as an error. If successful, the return value is true, else, it is false.

The function `odout' is used in order to delete a document specified by a URI.

int odout(ODEUM *odeum, const char *uri);
`odeum' specifies a database handle connected as a writer. `uri' specifies the string of the URI of a document. If successful, the return value is true, else, it is false. False is returned when no document corresponds to the specified URI.

The function `odoutbyid' is used in order to delete a document specified by an ID number.

int odoutbyid(ODEUM *odeum, int id);
`odeum' specifies a database handle connected as a writer. `id' specifies the ID number of a document. If successful, the return value is true, else, it is false. False is returned when no document corresponds to the specified ID number.

The function `odget' is used in order to retrieve a document specified by a URI.

ODDOC *odget(ODEUM *odeum, const char *uri);
`odeum' specifies a database handle. `uri' specifies the string of the URI of a document. If successful, the return value is the handle of the corresponding document, else, it is `NULL'. `NULL' is returned when no document corresponds to the specified URI. Because the handle of the return value is opened with the function `oddocopen', it should be closed with the function `oddocclose'.

The function `odgetbyid' is used in order to retrieve a document by an ID number.

ODDOC *odgetbyid(ODEUM *odeum, int id);
`odeum' specifies a database handle. `id' specifies the ID number of a document. If successful, the return value is the handle of the corresponding document, else, it is `NULL'. `NULL' is returned when no document corresponds to the specified ID number. Because the handle of the return value is opened with the function `oddocopen', it should be closed with the function `oddocclose'.

The function `odgetidbyuri' is used in order to retrieve the ID of the document specified by a URI.

int odgetidbyuri(ODEUM *odeum, const char *uri);
`odeum' specifies a database handle. `uri' specifies the string the URI of a document. If successful, the return value is the ID number of the document, else, it is -1. -1 is returned when no document corresponds to the specified URI.

The function `odcheck' is used in order to check whether the document specified by an ID number exists.

int odcheck(ODEUM *odeum, int id);
`odeum' specifies a database handle. `id' specifies the ID number of a document. The return value is true if the document exists, else, it is false.

The function `odsearch' is used in order to search the inverted index for documents including a particular word.

ODPAIR *odsearch(ODEUM *odeum, const char *word, int max, int *np);
`odeum' specifies a database handle. `word' specifies a searching word. `max' specifies the max number of documents to be retrieve. `np' specifies the pointer to a variable to which the number of the elements of the return value is assigned. If successful, the return value is the pointer to an array, else, it is `NULL'. Each element of the array is a pair of the ID number and the score of a document, and sorted in descending order of their scores. Even if no document corresponds to the specified word, it is not error but returns an dummy array. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. Note that each element of the array of the return value can be data of a deleted document.

The function `odsearchnum' is used in order to get the number of documents including a word.

int odsearchdnum(ODEUM *odeum, const char *word);
`odeum' specifies a database handle. `word' specifies a searching word. If successful, the return value is the number of documents including the word, else, it is -1. Because this function does not read the entity of the inverted index, it is faster than `odsearch'.

The function `oditerinit' is used in order to initialize the iterator of a database handle.

int oditerinit(ODEUM *odeum);
`odeum' specifies a database handle. If successful, the return value is true, else, it is false. The iterator is used in order to access every document stored in a database.

The function `oditernext' is used in order to get the next key of the iterator.

ODDOC *oditernext(ODEUM *odeum);
`odeum' specifies a database handle. If successful, the return value is the handle of the next document, else, it is `NULL'. `NULL' is returned when no document is to be get out of the iterator. It is possible to access every document by iteration of calling this function. However, it is not assured if updating the database is occurred while the iteration. Besides, the order of this traversal access method is arbitrary, so it is not assured that the order of string matches the one of the traversal access. Because the handle of the return value is opened with the function `oddocopen', it should be closed with the function `oddocclose'.

The function `odsync' is used in order to synchronize updating contents with the files and the devices.

int odsync(ODEUM *odeum);
`odeum' specifies a database handle connected as a writer. If successful, the return value is true, else, it is false. This function is useful when another process uses the connected database directory.

The function `odoptimize' is used in order to optimize a database.

int odoptimize(ODEUM *odeum);
`odeum' specifies a database handle connected as a writer. If successful, the return value is true, else, it is false. Elements of the deleted documents in the inverted index are purged.

The function `odname' is used in order to get the name of a database.

char *odname(ODEUM *odeum);
`odeum' specifies a database handle. If successful, the return value is the pointer to the region of the name of the database, else, it is `NULL'. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.

The function `odfsiz' is used in order to get the total size of database files.

double odfsiz(ODEUM *odeum);
`odeum' specifies a database handle. If successful, the return value is the total size of the database files, else, it is -1.0.

The function `odbnum' is used in order to get the total number of the elements of the bucket arrays in the inverted index.

int odbnum(ODEUM *odeum);
`odeum' specifies a database handle. If successful, the return value is the total number of the elements of the bucket arrays, else, it is -1.

The function `odbusenum' is used in order to get the total number of the used elements of the bucket arrays in the inverted index.

int odbusenum(ODEUM *odeum);
`odeum' specifies a database handle. If successful, the return value is the total number of the used elements of the bucket arrays, else, it is -1.

The function `oddnum' is used in order to get the number of the documents stored in a database.

int oddnum(ODEUM *odeum);
`odeum' specifies a database handle. If successful, the return value is the number of the documents stored in the database, else, it is -1.

The function `odwnum' is used in order to get the number of the words stored in a database.

int odwnum(ODEUM *odeum);
`odeum' specifies a database handle. If successful, the return value is the number of the words stored in the database, else, it is -1. Because of the I/O buffer, the return value may be less than the hard number.

The function `odwritable' is used in order to check whether a database handle is a writer or not.

int odwritable(ODEUM *odeum);
`odeum' specifies a database handle. The return value is true if the handle is a writer, false if not.

The function `odfatalerror' is used in order to check whether a database has a fatal error or not.

int odfatalerror(ODEUM *odeum);
`odeum' specifies a database handle. The return value is true if the database has a fatal error, false if not.

The function `odinode' is used in order to get the inode number of a database directory.

int odinode(ODEUM *odeum);
`odeum' specifies a database handle. The return value is the inode number of the database directory.

The function `odmtime' is used in order to get the last modified time of a database.

time_t odmtime(ODEUM *odeum);
`odeum' specifies a database handle. The return value is the last modified time of the database.

The function `odmerge' is used in order to merge plural database directories.

int odmerge(const char *name, const CBLIST *elemnames);
`name' specifies the name of a database directory to create. `elemnames' specifies a list of names of element databases. If successful, the return value is true, else, it is false. If two or more documents which have the same URL come in, the first one is adopted and the others are ignored.

The function `odremove' is used in order to remove a database directory.

int odremove(const char *name);
`name' specifies the name of a database directory. If successful, the return value is true, else, it is false. A database directory can contain databases of other APIs of QDBM, they are also removed by this function.

The function `oddocopen' is used in order to get a document handle.

ODDOC *oddocopen(const char *uri);
`uri' specifies the URI of a document. The return value is a document handle. The ID number of a new document is not defined. It is defined when the document is stored in a database.

The function `oddocclose' is used in order to close a document handle.

void oddocclose(ODDOC *doc);
`doc' specifies a document handle. Because the region of a closed handle is released, it becomes impossible to use the handle.

The function `oddocaddattr' is used in order to add an attribute to a document.

void oddocaddattr(ODDOC *doc, const char *name, const char *value);
`doc' specifies a document handle. `name' specifies the string of the name of an attribute. `value' specifies the string of the value of the attribute.

The function `oddocaddword' is used in order to add a word to a document.

void oddocaddword(ODDOC *doc, const char *normal, const char *asis);
`doc' specifies a document handle. `normal' specifies the string of the normalized form of a word. Normalized forms are treated as keys of the inverted index. If the normalized form of a word is an empty string, the word is not reflected in the inverted index. `asis' specifies the string of the appearance form of the word. Appearance forms are used after the document is retrieved by an application.

The function `oddocid' is used in order to get the ID number of a document.

int oddocid(const ODDOC *doc);
`doc' specifies a document handle. The return value is the ID number of a document.

The function `oddocuri' is used in order to get the URI of a document.

const char *oddocuri(const ODDOC *doc);
`doc' specifies a document handle. The return value is the string of the URI of a document.

The function `oddocgetattr' is used in order to get the value of an attribute of a document.

const char *oddocgetattr(const ODDOC *doc, const char *name);
`doc' specifies a document handle. `name' specifies the string of the name of an attribute. The return value is the string of the value of the attribute, or `NULL' if no attribute corresponds.

The function `oddocnwords' is used in order to get the list handle contains words in normalized form of a document.

const CBLIST *oddocnwords(const ODDOC *doc);
`doc' specifies a document handle. The return value is the list handle contains words in normalized form.

The function `oddocawords' is used in order to get the list handle contains words in appearance form of a document.

const CBLIST *oddocawords(const ODDOC *doc);
`doc' specifies a document handle. The return value is the list handle contains words in appearance form.

The function `oddocscores' is used in order to get the map handle contains keywords in normalized form and their scores.

CBMAP *oddocscores(const ODDOC *doc, int max, ODEUM *odeum);
`doc' specifies a document handle. `max' specifies the max number of keywords to get. `odeum' specifies a database handle with which the IDF for weighting is calculate. If it is `NULL', it is not used. The return value is the map handle contains keywords and their scores. Scores are expressed as decimal strings. Because the handle of the return value is opened with the function `cbmapopen', it should be closed with the function `cbmapclose' if it is no longer in use.

The function `odbreaktext' is used in order to break a text into words in appearance form.

CBLIST *odbreaktext(const char *text);
`text' specifies the string of a text. The return value is the list handle contains words in appearance form. Words are separated with space characters and such delimiters as period, comma and so on. Because the handle of the return value is opened with the function `cblistopen', it should be closed with the function `cblistclose' if it is no longer in use.

The function `odnormalizeword' is used in order to make the normalized form of a word.

char *odnormalizeword(const char *asis);
`asis' specifies the string of the appearance form of a word. The return value is is the string of the normalized form of the word. Alphabets of the ASCII code are unified into lower cases. Words composed of only delimiters are treated as empty strings. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.

The function `odpairsand' is used in order to get the common elements of two sets of documents.

ODPAIR *odpairsand(ODPAIR *apairs, int anum, ODPAIR *bpairs, int bnum, int *np);
`apairs' specifies the pointer to the former document array. `anum' specifies the number of the elements of the former document array. `bpairs' specifies the pointer to the latter document array. `bnum' specifies the number of the elements of the latter document array. `np' specifies the pointer to a variable to which the number of the elements of the return value is assigned. The return value is the pointer to a new document array whose elements commonly belong to the specified two sets. Elements of the array are sorted in descending order of their scores. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.

The function `odpairsor' is used in order to get the sum of elements of two sets of documents.

ODPAIR *odpairsor(ODPAIR *apairs, int anum, ODPAIR *bpairs, int bnum, int *np);
`apairs' specifies the pointer to the former document array. `anum' specifies the number of the elements of the former document array. `bpairs' specifies the pointer to the latter document array. `bnum' specifies the number of the elements of the latter document array. `np' specifies the pointer to a variable to which the number of the elements of the return value is assigned. The return value is the pointer to a new document array whose elements belong to both or either of the specified two sets. Elements of the array are sorted in descending order of their scores. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.

The function `odpairsnotand' is used in order to get the difference set of documents.

ODPAIR *odpairsnotand(ODPAIR *apairs, int anum, ODPAIR *bpairs, int bnum, int *np);
`apairs' specifies the pointer to the former document array. `anum' specifies the number of the elements of the former document array. `bpairs' specifies the pointer to the latter document array of the sum of elements. `bnum' specifies the number of the elements of the latter document array. `np' specifies the pointer to a variable to which the number of the elements of the return value is assigned. The return value is the pointer to a new document array whose elements belong to the former set but not to the latter set. Elements of the array are sorted in descending order of their scores. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use.

The function `odpairssort' is used in order to sort a set of documents in descending order of scores.

void odpairssort(ODPAIR *pairs, int pnum);
`pairs' specifies the pointer to a document array. `pnum' specifies the number of the elements of the document array.

The function `odlogarithm' is used in order to get the natural logarithm of a number.

double odlogarithm(double x);
`x' specifies a number. The return value is the natural logarithm of the number. If the number is equal to or less than 1.0, the return value is 0.0. This function is useful when an application calculates the IDF of search results.

The function `odvectorcosine' is used in order to get the cosine of the angle of two vectors.

double odvectorcosine(const int *avec, const int *bvec, int vnum);
`avec' specifies the pointer to one array of numbers. `bvec' specifies the pointer to the other array of numbers. `vnum' specifies the number of elements of each array. The return value is the cosine of the angle of two vectors. This function is useful when an application calculates similarity of documents.

The function `odsettuning' is used in order to set the global tuning parameters.

void odsettuning(int ibnum, int idnum, int cbnum, int csiz);
`ibnum' specifies the number of buckets for inverted indexes. `idnum' specifies the division number of inverted index. `cbnum' specifies the number of buckets for dirty buffers. `csiz' specifies the maximum bytes to use memory for dirty buffers. The default setting is equivalent to `odsettuning(32749, 7, 262139, 8388608)'. This function should be called before opening a handle.

The function `odanalyzetext' is used in order to break a text into words and store appearance forms and normalized form into lists.

void odanalyzetext(ODEUM *odeum, const char *text, CBLIST *awords, CBLIST *nwords);
`odeum' specifies a database handle. `text' specifies the string of a text. `awords' specifies a list handle into which appearance form is store. `nwords' specifies a list handle into which normalized form is store. If it is `NULL', it is ignored. Words are separated with space characters and such delimiters as period, comma and so on.

The function `odsetcharclass' is used in order to set the classes of characters used by `odanalyzetext'.

void odsetcharclass(ODEUM *odeum, const char *spacechars, const char *delimchars, const char *gluechars);
`odeum' specifies a database handle. `spacechars' spacifies a string contains space characters. `delimchars' spacifies a string contains delimiter characters. `gluechars' spacifies a string contains glue characters.

The function `odquery' is used in order to query a database using a small boolean query language.

ODPAIR *odquery(ODEUM *odeum, const char *query, int *np, CBLIST *errors);
`odeum' specifies a database handle. 'query' specifies the text of the query. `np' specifies the pointer to a variable to which the number of the elements of the return value is assigned. `errors' specifies a list handle into which error messages are stored. If it is `NULL', it is ignored. If successful, the return value is the pointer to an array, else, it is `NULL'. Each element of the array is a pair of the ID number and the score of a document, and sorted in descending order of their scores. Even if no document corresponds to the specified condition, it is not error but returns an dummy array. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. Note that each element of the array of the return value can be data of a deleted document.

Examples

The following example stores a document into the database.

#include <depot.h>
#include <cabin.h>
#include <odeum.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#define DBNAME   "index"

int main(int argc, char **argv){
  ODEUM *odeum;
  ODDOC *doc;
  CBLIST *awords;
  const char *asis;
  char *normal;
  int i;

  /* open the database */
  if(!(odeum = odopen(DBNAME, OD_OWRITER | OD_OCREAT))){
    fprintf(stderr, "odopen: %s\n", dperrmsg(dpecode));
    return 1;
  }

  /* get the document handle */
  doc = oddocopen("http://www.foo.bar/baz.txt");

  /* set attributes of the document */
  oddocaddattr(doc, "title", "Balcony Scene");
  oddocaddattr(doc, "author", "Shakespeare");

  /* break the text and get the word list */
  awords = odbreaktext("Parting is such sweet sorrow.");

  /* set each word into the document handle */
  for(i = 0; i < cblistnum(awords); i++){
    /* get one word of the list */
    asis = cblistval(awords, i, NULL);
    /* get the normalized form from the appearance form */
    normal = odnormalizeword(asis);
    /* add the word into the document handle */
    oddocaddword(doc, normal, asis);
    /* release the region of the normalized form */
    free(normal);
  }

  /* store the document into the database */
  if(!odput(odeum, doc, -1, 1)){
    fprintf(stderr, "odput: %s\n", dperrmsg(dpecode));
  }

  /* release the word list */
  cblistclose(awords);

  /* release the document handle */
  oddocclose(doc);

  /* close the database */
  if(!odclose(odeum)){
    fprintf(stderr, "odclose: %s\n", dperrmsg(dpecode));
    return 1;
  }

  return 0;
}

The following example retrieves documents.

#include <depot.h>
#include <cabin.h>
#include <odeum.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#define DBNAME   "index"

int main(int argc, char **argv){
  ODEUM *odeum;
  ODPAIR *pairs;
  ODDOC *doc;
  const CBLIST *words;
  const char *title, *author, *asis;
  int i, j, pnum;

  /* open the database */
  if(!(odeum = odopen(DBNAME, OD_OREADER))){
    fprintf(stderr, "odopen: %s\n", dperrmsg(dpecode));
    return 1;
  }

  /* retrieve documents */
  if((pairs = odsearch(odeum, "sorrow", -1, &pnum)) != NULL){

    /* scan each element of the document array */
    for(i = 0; i < pnum; i++){
      /* get the document handle */
      if(!(doc = odgetbyid(odeum, pairs[i].id))) continue;
      /* show the attributes */
      printf("URI: %s\n", oddocuri(doc));
      title = oddocgetattr(doc, "title");
      if(title) printf("TITLE: %s\n", title);
      author = oddocgetattr(doc, "author");
      if(author) printf("AUTHOR: %s\n", author);
      /* show words in appearance form */
      printf("WORDS:");
      words = oddocawords(doc);
      for(j = 0; j < cblistnum(words); j++){
        asis = cblistval(words, j, NULL);
        printf(" %s", asis);
      }
      putchar('\n');
      /* release the document handle */
      oddocclose(doc);
    }

    /* release the document array */
    free(pairs);

  } else {
    fprintf(stderr, "odsearch: %s\n", dperrmsg(dpecode));
  }

  /* close the database */
  if(!odclose(odeum)){
    fprintf(stderr, "odclose: %s\n", dperrmsg(dpecode));
    return 1;
  }

  return 0;
}

Notes

How to build programs using Odeum is the same as the case of Depot.

gcc -I/usr/local/include -o sample sample.c -L/usr/local/lib -lqdbm

If QDBM was built with POSIX thread enabled, the global variable `dpecode' is treated as thread specific data, and functions of Odeum are reentrant. In that case, they are thread-safe as long as a handle is not accessed by threads at the same time, on the assumption that `errno', `malloc', and so on are thread-safe.

If QDBM was built with ZLIB enabled, records in the database for document attributes are compressed. In that case, the size of the database is reduced to 30% or less. Thus, you should enable ZLIB if you use Odeum. A database of Odeum created without ZLIB enabled is not available on environment with ZLIB enabled, and vice versa. If ZLIB was not enabled but LZO, LZO is used instead.

Query Language

The query language of the function `odquery' is a basic language following this grammar:

expr ::= subexpr ( op subexpr )*
subexpr ::= WORD
subexpr ::= LPAREN expr RPAREN

Operators are "&" (AND), "|" (OR), and "!" (NOTAND). You can use parenthesis to group sub-expressions together in order to change order of operations. The given query is broken up using the function `odanalyzetext', so if you want to specify different text breaking rules, then make sure that you at least set "&", "|", "!", "(", and ")" to be delimiter characters. Consecutive words are treated as having an implicit "&" operator between them, so "zed shaw" is actually "zed & shaw".

The encoding of the query text should be the same with the encoding of target documents. Moreover, each of space characters, delimiter characters, and glue characters should be single byte.


Commands for Odeum

Odeum has the following command line interfaces.

The command `odmgr' is a utility for debugging Odeum and its applications. It features editing and checking of a database. It can be used for full-text search systems with shell scripts. This command is used in the following format. `name' specifies a database name. `file' specifies a file name, `expr' specifies the URI or the ID number of a document, `words' specifies searching words. `elems' specifies element databases.

odmgr create name
Create a database file.
odmgr put [-uri str] [-title str] [-author str] [-date str] [-wmax num] [-keep] name [file]
Add a document by reading a file. If `file' is omitted, the standard input is read and URI is needed.
odmgr out [-id] name expr
Delete a document specified by a URI.
odmgr get [-id] [-t|-h] name expr
Show a document specified by a URI. The output is the ID number and the URI of a document, in tab separated format.
odmgr search [-max num] [-or] [-idf] [-t|-h|-n] name words...
Retrieve documents including specified words. The first line of the output is the total number of hits and each word with its number of hits, in tab separated format. The second line and below are the ID numbers and the scores of documents, in tab separated format.
odmgr list [-t|-h] name
Show all documents in a database. Each line of the output is the ID number and the score of a document, in tab separated format.
odmgr optimize name
Optimize a database.
odmgr inform name
Output miscellaneous information.
odmgr merge name elems...
Merge plural databases.
odmgr remove name
Remove a database directory.
odmgr break [-h|-k|-s] [file]
Read a file and output words in the text. Each line of the output is the appearance form and the normalized form of a word, in tab separated format.
odmgr version
Output version information of QDBM.

Options feature the following.

  • -uri str : specify the URI of the document explicitly.
  • -title str : specify the title of the document.
  • -author str : specify the author of the document.
  • -date str : specify the modified date of the document.
  • -wmax num : specify the max number of words to be stored.
  • -keep : the storing mode is not to be overwrite.
  • -id : specify a document not by a URI but by an ID number.
  • -t : output the details of a document in tab separated format.
  • -h : output the details of a document in human-readable format.
  • -k : output keywords of a document.
  • -s : output summary of a document.
  • -max num : specify the max number of documents of the output.
  • -or : perform OR search, nut AND search.
  • -idf : tune scores with IDF.
  • -n : show ID numbers and scores only.

This command returns 0 on success, another on failure. The environment variable `QDBMDBGFD' specifies the file descriptor to output the history of updating the variable `dpecode'.

The command `odtest' is a utility for facility test and performance test. Check a database generated by the command or measure the execution time of the command. This command is used in the following format. `name' specifies a database name. `dnum' specifies the number of the documents. `wnum' specifies the number of words per document. `pnum' specifies the number of patterns of words.

odtest write [-tune ibnum idnum cbnum csiz] name dnum wnum pnum
Store documents with random attributes and random words.
odtest read name
Retrieve all documents of the database above.
odtest combo name
Perform combination test of various operations.
odtest wicked name dnum
Perform updating operations selected at random.

Options feature the following.

  • -tune ibnum idnum cbnum csiz : set tuning parameters.

This command returns 0 on success, another on failure. The environment variable `QDBMDBGFD' specifies the file descriptor to output the history of updating the variable `dpecode'.

The command `odidx' is a utility for indexing files on the local file system. This command is useful for a full-text search system of a Web site. Supported file format are plain text and HTML. Supported character encoding are US-ASCII and ISO-8859-1. The URI of each document is specified with the path of its file. Attributes named as `title' and `date' are given to each documents. When a document is already existing in the database, it is registered if its last modification time is newer, or it is ignored. Modification times are stored in the sub database `_mtime' in the main database directory. Score information are stored in the sub database `_score' in the main database directory. This command is used in the following format. `name' specifies a database name. `dir' specifies a directory name.

odidx register [-l file] [-wmax num] [-tsuf sufs] [-hsuf sufs] name [dir]
Register files in the specified directory. If `dir' is omitted, the current directory is specified.
odidx relate name
Add score information for relational document search to each documents in the database.
odidx purge name
Purge documents which are not existing on the local files system.

Options feature the following.

  • -l file : read a file and get list of paths of files to register. If `-' is specified, the standard input is read.
  • -wmax num : specify the max number of words to be stored in the document database.
  • -tsuf sufs : specify suffixes of plain text files in comma separated format. The default is `-tsuf .txt,.text'.
  • -hsuf sufs : specify suffixes of HTML files in comma separated format. The default is `-hsuf .html,.htm'.

This command returns 0 on success, another on failure.

Commands of Odeum make it easy to realize a full-text search system. For example, to register files which are under `/home/mikio' and whose suffix are `.txt', `.c', or `.h', perform the following command.

odidx register -tsuf ".txt,.c,.h" -hsuf "" casket /home/mikio

Thus, to retrieve documents which include `unix' and `posix' and show the top 8 terms, perform the following command.

odmgr search -max 8 -h casket "unix posix"

A database generated by `odidx' is available with the CGI script which is included in QDBM for full-text search.


File Format

File Format of Depot

The contents of a database file managed by Depot is divided roughly into the following three sections: the header section, the bucket section and the record section.

The header section places at the beginning of the file and its length is constant 48 bytes. The following information are stored in the header section.

  1. magic number: from offset 0, contains "[DEPOT]\n\f" for big endian or "[depot]\n\f" for little endian.
  2. version number: decimal string of the version number of the library.
  3. flags for wrappers: from offset 16, type of `int'.
  4. file size: from offset 24, type of `int'.
  5. number of the bucket: from offset 32, type of `int'.
  6. number of records: from offset 40, type of `int'.

The bucket section places after the header section and its length is determined according to the number of the bucket. Each element of the bucket stores an offset of the root node of each separate chain.

The record section places after the bucket section and occupies to the end of the file. The element of the record section contains the following information.

  1. flags: type of `int'.
  2. second hash value: type of `int'.
  3. size of the key: type of `int'.
  4. size of the value: type of `int'.
  5. size of the padding: type of `int'.
  6. offset of the left child: type of `int'.
  7. offset of the right child: type of `int'.
  8. entity of the key: serial bytes with variable length.
  9. entity of the value: serial bytes with variable length.
  10. padding data: void serial bytes with variable length.

File Format of Villa

Every data handled by Villa is stored in a database of Depot. Storing data is divided into meta data and logical pages. Logical pages can be classified into leaf nodes and non-leaf nodes. Meta data are such managing information as the number of records. Both of its key and its value are type of `int'. Leaf nodes hold records. Non-leaf nodes hold sparse index referring to pages.

Villa uses variable length numeric format (BER compression) to handle small natural number with frugal storage. A variable length numeric object is parsed from the top of the region and parsing ends at the byte of positive value. Each byte are evaluated as absolute value and calculated as little endian number based on the radix 128.

Record is logical unit of user data. Some records overlapping keys are shaped into one physical record. A Physical record is serialized in the following format.

  1. size of the key: type of variable length number
  2. entity of the key: serial bytes with variable length
  3. number of values: type of variable length number
  4. list of values: serial bytes repeating the following expressions
    1. size: type of variable length number
    2. entity of the key: serial bytes with variable length

Leaf node is physical unit to store a set of records. The key of a leaf node is its ID whose type is `int'. A leaf node is stored in a database of Depot with the following values. Its records are sorted in ascending order of each key.

  1. ID of the previous leaf: type of variable length number
  2. ID of the next leaf: type of variable length number
  3. list of records: concatenation of serialized records

Index is logical unit of a pointer to search for pages. An index is serialized int the following format.

  1. ID of the referring page: type of variable length number
  2. size of the key: type of variable length number
  3. entity of the key: serial bytes with variable length

Non-leaf node is physical unit to store a set of indexes. The key of a non-leaf node is its ID whose type is `int'. A non-leaf node is stored in a database of Depot with the following values. Its indexes are sorted in ascending order of each key.

  1. ID of the first child node: type of variable length number
  2. list of indexes: concatenation of serialized indexes

Notes

Because the database file is not sparse, move, copy, unlink, ftp, and so on with the file are possible. Because Depot reads and writes data without normalization of byte order, it is impossible to share the same file between the environment with different byte order.

When you distribute a database file of Depot or Villa via network, the MIME type suggested to be `application/x-qdbm'. Suffix of the file name is suggested to be `.qdb'. When you distribute a database directory of Curia, you may convert the directory tree to an archive of such type as TAR.

For the command `file' to recognize database files, append the following expressions into `magic' file.

0       string          [DEPOT]\n\f     QDBM, big endian
>12     string          x               \b, version=%s
>19     byte            ^1              \b, Hash
>19     byte            &1              \b, B+ tree
>19     byte            &2              \b (deflated:ZLIB)
>19     byte            &4              \b (deflated:LZO)
>19     byte            &8              \b (deflated:BZIP2)
>24     belong          x               \b, filesize=%d
>32     belong          x               \b, buckets=%d
>40     belong          x               \b, records=%d
0       string          [depot]\n\f     QDBM, little endian
>12     string          x               \b, version=%s
>16     byte            ^1              \b, Hash
>16     byte            &1              \b, B+ tree
>16     byte            &2              \b (deflated:ZLIB)
>16     byte            &4              \b (deflated:LZO)
>16     byte            &8              \b (deflated:BZIP2)
>24     lelong          x               \b, filesize=%d
>32     lelong          x               \b, buckets=%d
>40     lelong          x               \b, records=%d

Porting

One of the goal of QDBM is to work on all platforms which conform to POSIX. Even if some APIs are not implemented, QDBM should work. Moreover, it should be possible to build QDBM using compilers other than GCC. Porting to various platforms is performed to add a new `Makefile' or modify some parts of source files. As for APIs of C, some of the following files should be modified. Otherwise, you can create new files based on them.

  • Makefile.in : base of `Makefile', used by `./configure'.
  • myconf.h : configuration of system dependency.
  • depot.h : header of the basic API.
  • curia.h : header of the extended API.
  • relic.h : header of the NDBM-compatible API.
  • hovel.h : header of the GDBM-compatible API.
  • cabin.h : header of the utility API.
  • villa.h : header of the advanced API.
  • vista.h : header of the extended advanced API.
  • odeum.h : header of the inverted API.
  • myconf.c : implementation of system dependency.
  • depot.c : implementation of the basic API.
  • curia.c : implementation of the extended API.
  • relic.c : implementation of the NDBM-compatible API.
  • hovel.c : implementation of the GDBM-compatible API.
  • cabin.c : implementation of the utility API.
  • villa.c : implementation of the advanced API.
  • vista.c : implementation of the extended advanced API.
  • odeum.c : implementation of the inverted API.

On platforms which do not support file locking with `fcntl' call, you should append `-DMYNOLOCK' to the macro `CFLAGS' defined in `Makefile'. In that case, you should consider another exclusion control. As with it, on platforms without `mmap' call, you should append `-DMYNOMMAP' to `CFLAGS'. As for `mmap', its emulation using `malloc' and so on is provided. If other system calls are not implemented, you should define emulation by modification of `myconf.h' and `myconf.c'.

Because POSIX thread is used in C++ API, it is impossible to port C++ API to platforms without the package. Because JNI is used in Java API, you should pay attention to location of the headers and libraries. Moreover, you should consider such type definitions as `long long' or `int64'. Because APIs of Perl and Ruby use building commands provided with each language system, you should be knowledgeable about their specifications.


Bugs

Each document of QDBM should be calibrated by native English speakers.

There is no such bug which are found but not fixed, as crash by segmentation fault, unexpected data vanishing, memory leak and so on.

If you find any bug, report it to the author, with the information of the version of QDBM, the operating system and the compiler.

Databases created with QDBM version 1.7.13 or earlier are not compatible to ones of the later versions.


Frequently Asked Questions

Q. : Does QDBM support SQL?
A. : No, it does not. QDBM is not a RDBMS (Relational Database Management System). If you want an embedded RDBMS, use SQLite and so on.
Q. : After all, how different from GDBM (NDBM, SDBM, Berkeley DB)?
A. : Processing speed is higher, a database file is smaller, API is simpler. A highly important thing is that efficiency in time and space is very good when records are frequently overwritten, so, scalability in practical use is high. Moreover, even when constructing such a large database that the number of storing record is more than one million, processing speed does not slowdown deathly, filesize does not grow extremely. However, because other DBM or DBMS may be more suitable in some cases, comparing performance and functionality by yourself is suggested.
Q. : Which API should I use?
A. : If you search for records as complete accord, try Depot. If the scale is large, try Curia. If you access records in some order, try Villa. If the scale is large, try Vista. If you pursue the greatest number of records, build QDBM with ZLIB or LZO enabled and use Vista.
Q. : What is bibliography?
A. : Algorithms of QDBM are mainly based on the descriptions in `Data Structures and Algorithms' by Aho et al and `Algorithms in C' by Sedgewick.
Q. : Are there good sample codes for applications?
A. : Refer to the source code of commands of each API. `dptsv.c', `crtsv.c' and `vltsv.c' are simplest.
Q. : My database file has been broken. Why?
A. : In most cases, the reason is that your application did not close the database on exit. No matter whether it is a demon process or a CGI script, any application should close handling databases when it exits. Moreover, we should remember that a process of CGI may be killed by SIGPIPE or SIGTERM.
Q. : How robust are databases of QDBM?
A. : QDBM does not assure absolute robustness. A database may be broken if your operating system crashes. Although transaction of Villa can save a database from crashes of applications, it is inadequate to crashes of operating systems. So, you should consider multiplexing of a database or backup system if you use QDBM for mission critical applications.
Q: How should I use alignment of Depot and Curia?
A: If your application repeats writing with overwrite or concatenate mode. Alignment saves the rapid growth of the size of the database file. Because the best suited size of alignment of each application is different, you should learn it by experiment. For the meantime, about 32 is suitable.
Q. : How should I tune performance parameters of Villa?
A. : If you perform mainly ordering access, `lrecmax' and `nidxmax' should be larger. If you perform mainly random access, they should be less. If RAM of your system is abundant, `lcnum' and `ncnum' should be increased in order to improve performance. If ZLIB, LZO, or BZIP2 is enabled, increase `lrecmax' and compression efficiency is improved.
Q. : Which is the most preferable of ZLIB, LZO or BZIP2 for Villa?
A. : BZIP2 has the best compression retio. LZO has the best compression speed. ZLIB takes a mean position of them. If you don't have any special reason, using ZLIB is suggested. However, if updating of the database is frequent, LZO is more preferable. If updating of the database is very infrequently, BZIP2 is more preferable. Note that the license of LZO is the GNU LGPL.
Q. : What is `sparse file'?
A. : It is a file where some holes are. `Hole' means a block where any data has never written in. If a file system supports sparse file, holes are not allocated into any physical storage. As for QDBM, if a database is created with such flags as DP_OSPARSE, the bucket array is not initialized and its blocks become holes. According to that mechanism, you can use greatly huge hash tables. However, its performance is strongly depends on the setting of the file system.
Q. : Why Depot and Curia do not feature transaction?
A. : If an application implements its own transaction, inner transaction of database is superfluous. You can implement transaction for application easily with hash map provided by Cabin.
Q. : How should I tune the system for performance?
A. : Install more RAM on your machine than the size of a database. Then, enlarge I/O buffer and cut down on flushing dirty buffers. File system is also important. On Linux, although EXT2 is usually fastest, EXT3 is faster in some cases. ReiserFS is okey. The other modes of EXT3 are very slow. About other file systems, you should learn them by experiment.
Q. : Can I build QDBM using `cc' instead of `gcc'?
A. : Yes. Try to build QDBM with `LTmakefile'.
Q. : Can I build QDBM using Visual C++?
A. : Yes. Use `VCmakefile' instead of `Makefile'.
Q. : Can I use QDBM in other languages?
A. : As for PHP, Scheme (Gauche), and OCaml, interfaces of QDBM have been released. If you need it for another language, try to turn it out.
Q. : What does `QDBM' mean?
A. : `QDBM' stands for `Quick Database Manager'. It means that processing speed is high, and that you can write applications quickly.

Copying

QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License or any later version.

QDBM is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License along with QDBM (See the file `COPYING'); if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.

QDBM was written by Mikio Hirabayashi. You can contact the author by e-mail to `mikio@fallabs.com'.


qdbm-1.8.78/doc/icon16.png0000644000175000017500000000052307645737602014136 0ustar mikiomikio‰PNG  IHDR(-ScPLTEÿÿÿ jjjzzz–––®®®ÆÆÆ***ÒÒÒÖÖÖF:‚êêêBBBNNNbV’^zr¦.rRRRîîîþþþZZZ¦¦¦ºººŠŠŠåâërrr–޶²«Æ†††fffÊÆÚ?m¤!tRNS@æØfbKGDˆH pHYs  d_‘|IDATxœUÎÛƒ DQñV/Tä´ÓÚTþÿ+¥`,ìÇ•L2U%ë”lÆ*¶#µÏíXæ/Ÿàµµüêº÷ÒGðİ$ïBˆ&‚V€[ŸCû©¨÷¦Àü'Š2Bš3ðjâôågiòì²I­Ä ›<¶ájùÁfnWáúþ &â?‚†IEND®B`‚qdbm-1.8.78/doc/spex-ja.html0000644000175000017500000122225211426310750014553 0ustar mikiomikio Specifications of QDBM Version 1 (Japanese)

QDBMãƒãƒ¼ã‚¸ãƒ§ãƒ³ï¼‘基本仕様書

Copyright (C) 2000-2007 Mikio Hirabayashi
Last Update: Thu, 26 Oct 2006 15:00:20 +0900

目次

  1. 概è¦
  2. 特徴
  3. インストール
  4. Depot: 基本API
  5. Depot用コマンド
  6. Curia: æ‹¡å¼µAPI
  7. Curia用コマンド
  8. Relic: NDBM互æ›API
  9. Relic用コマンド
  10. Hovel: GDBM互æ›API
  11. Hovel用コマンド
  12. Cabin: ユーティリティAPI
  13. Cabin用コマンド
  14. Villa: 上級API
  15. Villa用コマンド
  16. Odeum: 転置API
  17. Odeum用コマンド
  18. ファイルフォーマット
  19. ç§»æ¤æ–¹æ³•
  20. ãƒã‚°
  21. よãèžã‹ã‚Œã‚‹è³ªå•
  22. ライセンス

概è¦

QDBMã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’扱ã†ãƒ«ãƒ¼ãƒãƒ³ç¾¤ã®ãƒ©ã‚¤ãƒ–ラリã§ã‚る。データベースã¨ã„ã£ã¦ã‚‚å˜ç´”ãªã‚‚ã®ã§ã‚りã€ã‚­ãƒ¼ã¨å€¤ã®ãƒšã‚¢ã‹ã‚‰ãªã‚‹ãƒ¬ã‚³ãƒ¼ãƒ‰ç¾¤ã‚’æ ¼ç´ã—ãŸãƒ‡ãƒ¼ã‚¿ãƒ•ァイルã§ã‚る。キーã¨å€¤ã¯ä»»æ„ã®é•·ã•ã‚’æŒã¤ä¸€é€£ã®ãƒã‚¤ãƒˆåˆ—ã§ã‚ã‚Šã€æ–‡å­—列ã§ã‚‚ãƒã‚¤ãƒŠãƒªã§ã‚‚扱ã†ã“ã¨ãŒã§ãã‚‹ã€‚ãƒ†ãƒ¼ãƒ–ãƒ«ã‚„ãƒ‡ãƒ¼ã‚¿åž‹ã®æ¦‚念ã¯ãªã„。レコードã¯ãƒãƒƒã‚·ãƒ¥è¡¨ã¾ãŸã¯B+木ã§ç·¨æˆã•れる。

ãƒãƒƒã‚·ãƒ¥è¡¨ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã§ã¯ã€ã‚­ãƒ¼ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹å†…ã§ä¸€æ„ã§ã‚りã€ã‚­ãƒ¼ãŒé‡è¤‡ã™ã‚‹è¤‡æ•°ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’æ ¼ç´ã™ã‚‹ã“ã¨ã¯ã§ããªã„。ã“ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«å¯¾ã—ã¦ã¯ã€ã‚­ãƒ¼ã¨å€¤ã‚’指定ã—ã¦ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’æ ¼ç´ã—ãŸã‚Šã€ã‚­ãƒ¼ã‚’指定ã—ã¦å¯¾å¿œã™ã‚‹ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’削除ã—ãŸã‚Šã€ã‚­ãƒ¼ã‚’指定ã—ã¦å¯¾å¿œã™ã‚‹ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’検索ã—ãŸã‚Šã™ã‚‹ã“ã¨ãŒã§ãる。ã¾ãŸã€ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«æ ¼ç´ã—ã¦ã‚ã‚‹å…¨ã¦ã®ã‚­ãƒ¼ã‚’é †ä¸åŒã«ä¸€ã¤ãšã¤å–り出ã™ã“ã¨ã‚‚ã§ãる。ã“ã®ã‚ˆã†ãªæ“作ã¯ã€UNIX標準ã§å®šç¾©ã•れã¦ã„ã‚‹DBMライブラリãŠã‚ˆã³ãã®è¿½å¾“ã§ã‚ã‚‹NDBMã‚„GDBMã«é¡žã™ã‚‹ã‚‚ã®ã§ã‚る。QDBMã¯DBMã®ã‚ˆã‚Šè‰¯ã„代替ã¨ã—ã¦åˆ©ç”¨ã™ã‚‹ã“ã¨ãŒã§ãる。

B+木ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã§ã¯ã€ã‚­ãƒ¼ãŒé‡è¤‡ã™ã‚‹è¤‡æ•°ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’æ ¼ç´ã™ã‚‹ã“ã¨ãŒã§ãる。ã“ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«å¯¾ã—ã¦ã¯ã€ãƒãƒƒã‚·ãƒ¥è¡¨ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã¨åŒæ§˜ã«ã€ã‚­ãƒ¼ã‚’指定ã—ã¦ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’æ ¼ç´ã—ãŸã‚Šå–り出ã—ãŸã‚Šå‰Šé™¤ã—ãŸã‚Šã™ã‚‹ã“ã¨ãŒã§ãる。レコードã¯ãƒ¦ãƒ¼ã‚¶ãŒæŒ‡ç¤ºã—ãŸæ¯”較関数ã«åŸºã¥ã„ã¦æ•´åˆ—ã•ã‚Œã¦æ ¼ç´ã•れる。カーソルを用ã„ã¦å„レコードを昇順ã¾ãŸã¯é™é †ã§å‚ç…§ã™ã‚‹ã“ã¨ãŒã§ãる。ã“ã®æ©Ÿæ§‹ã«ã‚ˆã£ã¦ã€æ–‡å­—列ã®å‰æ–¹ä¸€è‡´æ¤œç´¢ã‚„数値ã®ç¯„囲検索ãŒå¯èƒ½ã«ãªã‚‹ã€‚ã¾ãŸã€B+木ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã§ã¯ãƒˆãƒ©ãƒ³ã‚¶ã‚¯ã‚·ãƒ§ãƒ³ãŒåˆ©ç”¨ã§ãる。

QDBMã¯Cã§è¨˜è¿°ã•れã€Cã€C++ã€Javaã€PerlãŠã‚ˆã³Rubyã®APIã¨ã—ã¦æä¾›ã•れる。QDBMã¯POSIX準拠ã®APIã‚’å‚™ãˆã‚‹ãƒ—ラットフォームã§åˆ©ç”¨ã§ãる。QDBMã¯GNU Lesser General Public Licenseã«åŸºã¥ãフリーソフトウェアã§ã‚る。


特徴

効率的ãªãƒãƒƒã‚·ãƒ¥ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®å®Ÿè£…

QDBMã¯GDBMã‚’å‚è€ƒã«æ¬¡ã®ä¸‰ç‚¹ã‚’目標ã¨ã—ã¦é–‹ç™ºã•れãŸã€‚処ç†ãŒã‚ˆã‚Šé«˜é€Ÿã§ã‚ã‚‹ã“ã¨ã€ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルãŒã‚ˆã‚Šå°ã•ã„ã“ã¨ã€APIãŒã‚ˆã‚Šå˜ç´”ã§ã‚ã‚‹ã“ã¨ã€‚ã“れらã®ç›®æ¨™ã¯é”æˆã•れã¦ã„る。ã¾ãŸã€GDBMã¨åŒæ§˜ã«ã€ä¼çµ±çš„ãªDBMãŒæŠ±ãˆã‚‹ä¸‰ã¤ã®åˆ¶é™äº‹é …を回é¿ã—ã¦ã„る。ã™ãªã‚ã¡ã€ãƒ—ロセス内ã§è¤‡æ•°ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’扱ã†ã“ã¨ãŒã§ãã€ã‚­ãƒ¼ã¨å€¤ã®ã‚µã‚¤ã‚ºã«åˆ¶é™ãŒãªãã€ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルãŒã‚¹ãƒ‘ースã§ã¯ãªã„。

QDBMã¯ãƒ¬ã‚³ãƒ¼ãƒ‰ã®æŽ¢ç´¢ã«ãƒãƒƒã‚·ãƒ¥ã‚¢ãƒ«ã‚´ãƒªã‚ºãƒ ã‚’用ã„る。ãƒã‚±ãƒƒãƒˆé…列ã«å分ãªè¦ç´ æ•°ãŒã‚れã°ã€ãƒ¬ã‚³ãƒ¼ãƒ‰ã®æŽ¢ç´¢ã«ã‹ã‹ã‚‹æ™‚間計算é‡ã¯ O(1) ã§ã‚る。ã™ãªã‚ã¡ã€ãƒ¬ã‚³ãƒ¼ãƒ‰ã®æŽ¢ç´¢ã«å¿…è¦ãªæ™‚é–“ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®è¦æ¨¡ã«é–¢ã‚らãšä¸€å®šã§ã‚る。追加や削除ã«é–¢ã—ã¦ã‚‚åŒæ§˜ã§ã‚る。ãƒãƒƒã‚·ãƒ¥å€¤ã®è¡çªã¯ã‚»ãƒ‘レートãƒã‚§ãƒ¼ãƒ³æ³•ã§ç®¡ç†ã™ã‚‹ã€‚ãƒã‚§ãƒ¼ãƒ³ã®ãƒ‡ãƒ¼ã‚¿æ§‹é€ ã¯äºŒåˆ†æŽ¢ç´¢æœ¨ã§ã‚る。ãƒã‚±ãƒƒãƒˆé…列ã®è¦ç´ æ•°ãŒè‘—ã—ãå°‘ãªã„å ´åˆã§ã‚‚ã€æŽ¢ç´¢ç­‰ã®æ™‚間計算é‡ã¯ O(log n) ã«æŠ‘ãˆã‚‰ã‚Œã‚‹ã€‚

QDBMã¯ãƒã‚±ãƒƒãƒˆé…列を全ã¦RAM上ã«ä¿æŒã™ã‚‹ã“ã¨ã«ã‚ˆã£ã¦ã€å‡¦ç†ã®é«˜é€ŸåŒ–を図る。ãƒã‚±ãƒƒãƒˆé…列ãŒRAM上ã«ã‚れã°ã€ã»ã¼1パスã®ãƒ•ァイルæ“作ã§ãƒ¬ã‚³ãƒ¼ãƒ‰ã«è©²å½“ã™ã‚‹ãƒ•ァイル上ã®é ˜åŸŸã‚’å‚ç…§ã™ã‚‹ã“ã¨ãŒã§ãる。ファイルã«è¨˜éŒ²ã•れãŸãƒã‚±ãƒƒãƒˆé…列㯠`read' コールã§RAM上ã«èª­ã¿è¾¼ã‚€ã®ã§ã¯ãªãã€`mmap' コールã§RAMã«ç›´æŽ¥ãƒžãƒƒãƒ”ングã•れる。ã—ãŸãŒã£ã¦ã€ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«æŽ¥ç¶šã™ã‚‹éš›ã®æº–å‚™æ™‚é–“ãŒæ¥µã‚ã¦çŸ­ãã€ã¾ãŸã€è¤‡æ•°ã®ãƒ—ロセスã§ãƒ¡ãƒ¢ãƒªãƒžãƒƒãƒ—を共有ã™ã‚‹ã“ã¨ãŒã§ãる。

ãƒã‚±ãƒƒãƒˆé…列ã®è¦ç´ æ•°ãŒæ ¼ç´ã™ã‚‹ãƒ¬ã‚³ãƒ¼ãƒ‰æ•°ã®åŠåˆ†ã»ã©ã§ã‚れã°ã€ãƒ‡ãƒ¼ã‚¿ã®æ€§è³ªã«ã‚ˆã£ã¦å¤šå°‘å‰å¾Œã™ã‚‹ãŒã€ãƒãƒƒã‚·ãƒ¥å€¤ã®è¡çªçއã¯56.7%ã»ã©ã§ã‚る(等å€ã ã¨36.8%ã€2å€ã ã¨21.3%ã€4å€ã ã¨11.5%ã€8å€ã ã¨6.0%ã»ã©ï¼‰ã€‚ãã®ã‚ˆã†ãªå ´åˆã€å¹³å‡2パス以下ã®ãƒ•ァイルæ“作ã§ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’探索ã™ã‚‹ã“ã¨ãŒã§ãる。ã“れを性能指標ã¨ã™ã‚‹ãªã‚‰ã°ã€ä¾‹ãˆã°100万個ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’æ ¼ç´ã™ã‚‹ãŸã‚ã«ã¯50万è¦ç´ ã®ãƒã‚±ãƒƒãƒˆé…åˆ—ãŒæ±‚ã‚られる。ãƒã‚±ãƒƒãƒˆé…列ã®å„è¦ç´ ã¯4ãƒã‚¤ãƒˆã§ã‚る。ã™ãªã‚ã¡ã€2Mãƒã‚¤ãƒˆã®RAMãŒåˆ©ç”¨ã§ãれã°100万レコードã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãŒæ§‹ç¯‰ã§ãる。

QDBMã«ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«æŽ¥ç¶šã™ã‚‹ãƒ¢ãƒ¼ãƒ‰ã¨ã—ã¦ã€ã€Œãƒªãƒ¼ãƒ€ã€ã¨ã€Œãƒ©ã‚¤ã‚¿ã€ã®äºŒç¨®é¡žãŒã‚る。リーダã¯èª­ã¿è¾¼ã¿å°‚用ã§ã‚りã€ãƒ©ã‚¤ã‚¿ã¯èª­ã¿æ›¸ã両用ã§ã‚る。データベースã«ã¯ãƒ•ァイルロックã«ã‚ˆã£ã¦ãƒ—ロセス間ã§ã®æŽ’他制御ãŒè¡Œã‚ã‚Œã‚‹ã€‚ãƒ©ã‚¤ã‚¿ãŒæŽ¥ç¶šã—ã¦ã„ã‚‹é–“ã¯ã€ä»–ã®ãƒ—ロセスã¯ãƒªãƒ¼ãƒ€ã¨ã—ã¦ã‚‚ライタã¨ã—ã¦ã‚‚接続ã§ããªã„ã€‚ãƒªãƒ¼ãƒ€ãŒæŽ¥ç¶šã—ã¦ã„ã‚‹é–“ã¯ã€ä»–ã®ãƒ—ロセスã®ãƒªãƒ¼ãƒ€ã¯æŽ¥ç¶šã§ãã‚‹ãŒã€ãƒ©ã‚¤ã‚¿ã¯æŽ¥ç¶šã§ããªã„。ã“ã®æ©Ÿæ§‹ã«ã‚ˆã£ã¦ã€ãƒžãƒ«ãƒã‚¿ã‚¹ã‚¯ç’°å¢ƒã§ã®åŒæ™‚接続ã«ä¼´ã†ãƒ‡ãƒ¼ã‚¿ã®æ•´åˆæ€§ãŒä¿è¨¼ã•れる。

ä¼çµ±çš„ãªDBMã«ã¯ãƒ¬ã‚³ãƒ¼ãƒ‰ã®è¿½åŠ æ“作ã«é–¢ã—ã¦ã€ŒæŒ¿å…¥ã€ãƒ¢ãƒ¼ãƒ‰ã¨ã€Œç½®æ›ã€ãƒ¢ãƒ¼ãƒ‰ãŒã‚る。å‰è€…ã§ã¯ã€ã‚­ãƒ¼ãŒæ—¢å­˜ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã¨é‡è¤‡ã™ã‚‹éš›ã«æ—¢å­˜ã®å€¤ã‚’残ã™ã€‚後者ã§ã¯ã€ã‚­ãƒ¼ãŒæ—¢å­˜ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã¨é‡è¤‡ã—ãŸéš›ã«æ–°ã—ã„値ã«ç½®ãæ›ãˆã‚‹ã€‚QDBMã¯ãã®ï¼’ã¤ã«åŠ ãˆã¦ã€Œé€£çµã€ãƒ¢ãƒ¼ãƒ‰ãŒã‚る。既存ã®å€¤ã®æœ«å°¾ã«æŒ‡å®šã•れãŸå€¤ã‚’連çµã—ã¦æ ¼ç´ã™ã‚‹æ“作ã§ã‚る。レコードã®å€¤ã‚’é…列ã¨ã—ã¦æ‰±ã†å ´åˆã€è¦ç´ ã‚’追加ã™ã‚‹ã«ã¯é€£çµãƒ¢ãƒ¼ãƒ‰ãŒå½¹ã«ç«‹ã¤ã€‚ã¾ãŸã€DBMã§ã¯ãƒ¬ã‚³ãƒ¼ãƒ‰ã®å€¤ã‚’å–り出ã™éš›ã«ã¯ãã®å…¨ã¦ã®é ˜åŸŸã‚’処ç†å¯¾è±¡ã«ã™ã‚‹ã—ã‹æ–¹æ³•ãŒãªã„ãŒã€QDBMã§ã¯å€¤ã®é ˜åŸŸã®ä¸€éƒ¨ã®ã¿ã‚’é¸æŠžã—ã¦å–り出ã™ã“ã¨ãŒã§ãる。レコードã®å€¤ã‚’é…列ã¨ã—ã¦æ‰±ã†å ´åˆã«ã¯ã“ã®æ©Ÿèƒ½ã‚‚å½¹ã«ç«‹ã¤ã€‚

一般的ã«ã€ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®æ›´æ–°å‡¦ç†ã‚’ç¶šã‘ã‚‹ã¨ãƒ•ァイル内ã®åˆ©ç”¨å¯èƒ½é ˜åŸŸã®æ–­ç‰‡åŒ–ãŒèµ·ãã€ãƒ•ァイルã®ã‚µã‚¤ã‚ºãŒè‚¥å¤§åŒ–ã—ã¦ã—ã¾ã†ã€‚QDBMã¯éš£æŽ¥ã™ã‚‹ä¸è¦é ˜åŸŸã‚’連çµã—ã¦å†åˆ©ç”¨ã—ã€ã¾ãŸãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®æœ€é©åŒ–機能を備ãˆã‚‹ã“ã¨ã«ã‚ˆã£ã¦ã“ã®å•題ã«å¯¾å‡¦ã™ã‚‹ã€‚既存ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã®å€¤ã‚’より大ããªã‚µã‚¤ã‚ºã®å€¤ã«ä¸Šæ›¸ãã™ã‚‹å ´åˆã€ãã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã®é ˜åŸŸã‚’ファイル中ã®åˆ¥ã®ä½ç½®ã«ç§»å‹•ã•ã›ã‚‹å¿…è¦ãŒã‚る。ã“ã®å‡¦ç†ã®æ™‚間計算é‡ã¯ãƒ¬ã‚³ãƒ¼ãƒ‰ã®ã‚µã‚¤ã‚ºã«ä¾å­˜ã™ã‚‹ã®ã§ã€å€¤ã‚’æ‹¡å¼µã—ã¦ã„ãå ´åˆã«ã¯åŠ¹çŽ‡ãŒæ‚ªã„。ã—ã‹ã—ã€QDBMã¯ã‚¢ãƒ©ã‚¤ãƒ³ãƒ¡ãƒ³ãƒˆã«ã‚ˆã£ã¦ã“ã®å•題ã«å¯¾å‡¦ã™ã‚‹ã€‚増分ãŒãƒ‘ディングã«åŽã¾ã‚Œã°é ˜åŸŸã‚’移動ã•ã›ã‚‹å¿…è¦ã¯ãªã„。

多ãã®ãƒ•ァイルシステムã§ã¯ã€2GBã‚’è¶Šãˆã‚‹ã‚µã‚¤ã‚ºã®ãƒ•ァイルを扱ã†ã“ã¨ãŒã§ããªã„。ã“ã®å•題ã«å¯¾å‡¦ã™ã‚‹ãŸã‚ã«ã€QDBMã¯è¤‡æ•°ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルをå«ã‚€ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã‹ã‚‰ãªã‚‹ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’æ‰±ã†æ©Ÿèƒ½ã‚’æä¾›ã™ã‚‹ã€‚レコードをã©ã®ãƒ•ã‚¡ã‚¤ãƒ«ã«æ ¼ç´ã™ã‚‹ã‹ã¯ã‚­ãƒ¼ã«åˆ¥ã®ãƒãƒƒã‚·ãƒ¥é–¢æ•°ã‚’é©ç”¨ã™ã‚‹ã“ã¨ã«ã‚ˆã£ã¦æ±ºã‚られる。ã“ã®æ©Ÿèƒ½ã«ã‚ˆã£ã¦ã€ç†è«–çš„ã«ã¯ãƒ¬ã‚³ãƒ¼ãƒ‰ã®åˆè¨ˆã‚µã‚¤ã‚ºãŒ1TBã¾ã§ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’構築ã™ã‚‹ã“ã¨ãŒã§ãる。ã¾ãŸã€ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルを複数ã®ãƒ‡ã‚£ã‚¹ã‚¯ã«æŒ¯ã‚Šåˆ†ã‘ã‚‹ã“ã¨ãŒã§ãã‚‹ãŸã‚ã€RAID-0(ストライピング)ã«è¦‹ã‚‰ã‚Œã‚‹ã‚ˆã†ãªæ›´æ–°æ“作ã®é«˜é€ŸåŒ–ãŒæœŸå¾…ã§ãる。NFS等を利用ã™ã‚Œã°è¤‡æ•°ã®ãƒ•ァイルサーãƒã«ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’分散ã•ã›ã‚‹ã“ã¨ã‚‚ã§ãる。

便利ãªB+木データベースã®å®Ÿè£…

B+木データベースã¯ãƒãƒƒã‚·ãƒ¥ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚ˆã‚Šé…ã„ãŒã€ãƒ¦ãƒ¼ã‚¶ãŒå®šç¾©ã—ãŸé †åºã«åŸºã¥ã„ã¦å„レコードをå‚ç…§ã§ãã‚‹ã“ã¨ãŒç‰¹é•·ã§ã‚る。B+木ã¯è¤‡æ•°ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’整列ã•ã›ãŸçŠ¶æ…‹ã§è«–ç†çš„ãªãƒšãƒ¼ã‚¸ã«ã¾ã¨ã‚ã¦ç®¡ç†ã™ã‚‹ã€‚å„ページã«å¯¾ã—ã¦ã¯B木ã™ãªã‚ã¡å¤šé€²å¹³è¡¡æœ¨ã«ã‚ˆã£ã¦éšŽå±¤åŒ–ã•れãŸç–Žã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹ãŒç¶­æŒã•れる。ã—ãŸãŒã£ã¦ã€å„ãƒ¬ã‚³ãƒ¼ãƒ‰ã®æŽ¢ç´¢ç­‰ã«ã‹ã‹ã‚‹æ™‚間計算é‡ã¯ O(log n) ã§ã‚る。å„レコードを順番ã«å‚ç…§ã™ã‚‹ãŸã‚ã«ã‚«ãƒ¼ã‚½ãƒ«ãŒæä¾›ã•れる。カーソルã®å ´æ‰€ã¯ã‚­ãƒ¼ã‚’指定ã—ã¦é£›ã°ã™ã“ã¨ãŒã§ãã€ã¾ãŸç¾åœ¨ã®å ´æ‰€ã‹ã‚‰æ¬¡ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã«é€²ã‚ãŸã‚Šå‰ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã«æˆ»ã—ãŸã‚Šã™ã‚‹ã“ã¨ãŒã§ãる。å„ページã¯åŒæ–¹å‘リンクリストã§ç·¨æˆã•れるã®ã§ã€ã‚«ãƒ¼ã‚½ãƒ«ã‚’å‰å¾Œã«ç§»å‹•ã•ã›ã‚‹æ™‚間計算é‡ã¯ O(1) ã§ã‚る。

B+木データベースã¯ä¸Šè¿°ã®ãƒãƒƒã‚·ãƒ¥ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’基盤ã¨ã—ã¦å®Ÿè£…ã•れる。B+木ã®å„ページã¯ãƒãƒƒã‚·ãƒ¥ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã¨ã—ã¦è¨˜éŒ²ã•れるã®ã§ã€ãƒãƒƒã‚·ãƒ¥ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®è¨˜æ†¶ç®¡ç†ã®åŠ¹çŽ‡æ€§ã‚’ç¶™æ‰¿ã—ã¦ã„る。B+木ã§ã¯å„レコードã®ãƒ˜ãƒƒãƒ€ãŒå°ã•ãã€å„ページã®ã‚¢ãƒ©ã‚¤ãƒ³ãƒ¡ãƒ³ãƒˆã¯ãƒšãƒ¼ã‚¸ã‚µã‚¤ã‚ºã«å¿œã˜ã¦èª¿æ•´ã•れるã®ã§ã€ã»ã¨ã‚“ã©ã®å ´åˆã€ãƒãƒƒã‚·ãƒ¥ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«è¼ƒã¹ã¦ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルã®ã‚µã‚¤ã‚ºãŒåŠæ¸›ã™ã‚‹ã€‚B+木を更新ã™ã‚‹éš›ã«ã¯å¤šãã®ãƒšãƒ¼ã‚¸ã‚’æ“作ã™ã‚‹å¿…è¦ãŒã‚ã‚‹ãŒã€QDBMã¯ãƒšãƒ¼ã‚¸ã‚’キャッシュã™ã‚‹ã“ã¨ã«ã‚ˆã£ã¦ãƒ•ァイルæ“作を減らã—ã¦å‡¦ç†ã‚’効率化ã™ã‚‹ã€‚ã»ã¨ã‚“ã©ã®å ´åˆã€ç–Žã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹å…¨ä½“ãŒãƒ¡ãƒ¢ãƒªä¸Šã«ã‚­ãƒ£ãƒƒã‚·ãƒ¥ã•れるã®ã§ã€å„レコードをå‚ç…§ã™ã‚‹ã®ã«å¿…è¦ãªãƒ•ァイルæ“作ã¯å¹³å‡1パス以下ã§ã‚る。

B+木データベースã¯ãƒˆãƒ©ãƒ³ã‚¶ã‚¯ã‚·ãƒ§ãƒ³æ©Ÿæ§‹ã‚’æä¾›ã™ã‚‹ã€‚トランザクションを開始ã—ã¦ã‹ã‚‰çµ‚了ã™ã‚‹ã¾ã§ã®ä¸€é€£ã®æ“作を一括ã—ã¦ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«ã‚³ãƒŸãƒƒãƒˆã—ãŸã‚Šã€ä¸€é€£ã®æ›´æ–°æ“作を破棄ã—ã¦ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®çŠ¶æ…‹ã‚’ãƒˆãƒ©ãƒ³ã‚¶ã‚¯ã‚·ãƒ§ãƒ³ã®é–‹å§‹å‰ã®çŠ¶æ…‹ã«ãƒ­ãƒ¼ãƒ«ãƒãƒƒã‚¯ã—ãŸã‚Šã™ã‚‹ã“ã¨ãŒã§ãる。トランザクションã®é–“ã«ã‚¢ãƒ—リケーションã®ãƒ—ロセスãŒã‚¯ãƒ©ãƒƒã‚·ãƒ¥ã—ã¦ã‚‚データベースファイルã¯ç ´å£Šã•れãªã„。

å¯é€†ãƒ‡ãƒ¼ã‚¿åœ§ç¸®ãƒ©ã‚¤ãƒ–ラリã§ã‚ã‚‹ZLIBã‹LZOã‹BZIP2を有効化ã—ã¦QDBMをビルドã™ã‚‹ã¨ã€B+木ã®å„ページã®å†…容ã¯åœ§ç¸®ã•れã¦ãƒ•ã‚¡ã‚¤ãƒ«ã«æ›¸ãè¾¼ã¾ã‚Œã‚‹ã€‚åŒä¸€ãƒšãƒ¼ã‚¸å†…ã®å„レコードã¯ä¼¼ãŸã‚ˆã†ãªãƒ‘ターンをæŒã¤ãŸã‚ã€Lempel-Zivãªã©ã®ã‚¢ãƒ«ã‚´ãƒªã‚ºãƒ ã‚’é©ç”¨ã™ã‚‹ã¨é«˜ã„åœ§ç¸®åŠ¹çŽ‡ãŒæœŸå¾…ã§ãる。テキストデータを扱ã†å ´åˆã€ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®ã‚µã‚¤ã‚ºãŒå…ƒã®25%程度ã«ãªã‚‹ã€‚データベースã®è¦æ¨¡ãŒå¤§ããディスクI/OãŒãƒœãƒˆãƒ«ãƒãƒƒã‚¯ã¨ãªã‚‹å ´åˆã¯ã€åœ§ç¸®æ©Ÿèƒ½ã‚’有効化ã™ã‚‹ã¨å‡¦ç†é€Ÿåº¦ãŒå¤§å¹…ã«æ”¹å–„ã•れる。

å˜ç´”ã ãŒå¤šæ§˜ãªã‚¤ãƒ³ã‚¿ãƒ•ェース群

QDBMã®APIã¯éžå¸¸ã«å˜ç´”ã§ã‚る。ANSI Cã§å®šç¾©ã•れ㟠`FILE' ãƒã‚¤ãƒ³ã‚¿ã‚’用ã„ãŸé€šå¸¸ã®ãƒ•ァイル入出力ã¨åŒã˜ã‚ˆã†ã«ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルã«å¯¾ã™ã‚‹å…¥å‡ºåŠ›ã‚’è¡Œã†ã“ã¨ãŒã§ãる。QDBMã®åŸºæœ¬APIã§ã¯ã€ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®å®Ÿä½“ã¯å˜ä¸€ã®ãƒ•ァイルã«è¨˜éŒ²ã•れる。拡張APIã§ã¯ã€ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®å®Ÿä½“ã¯å˜ä¸€ã®ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã«å«ã¾ã‚Œã‚‹è¤‡æ•°ã®ãƒ•ァイルã«è¨˜éŒ²ã•れる。二ã¤ã®APIã¯äº’ã„ã«é…·ä¼¼ã—ã¦ã„ã‚‹ã®ã§ã€ã‚¢ãƒ—リケーションを一方ã‹ã‚‰ä»–æ–¹ã«ç§»æ¤ã™ã‚‹ã“ã¨ã¯ãŸã‚„ã™ã„。

NDBMãŠã‚ˆã³GDBMã«äº’æ›ã™ã‚‹APIã‚‚æä¾›ã•れる。NDBMã‚„GDBMã®ã‚¢ãƒ—リケーションã¯å¸‚å ´ã«æ•°å¤šã存在ã™ã‚‹ãŒã€ãれらをQDBMã«ç§»æ¤ã™ã‚‹ã®ã¯ãŸã‚„ã™ã„。ã»ã¨ã‚“ã©ã®å ´åˆã€ãƒ˜ãƒƒãƒ€ãƒ•ァイルã®å–り込ã¿ï¼ˆ#includeï¼‰ã‚’æ›¸ãæ›ãˆã¦ã‚³ãƒ³ãƒ‘イルã—ãªãŠã›ã°ã‚ˆã„。ãŸã ã—ã€ã‚ªãƒªã‚¸ãƒŠãƒ«ã®NDBMã‚„GDBMã§ä½œæˆã—ãŸãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルをQDBMã§æ‰±ã†ã“ã¨ã¯ã§ããªã„。

メモリ上ã§ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’ç°¡å˜ã«æ‰±ã†ãŸã‚ã«ã€ãƒ¦ãƒ¼ãƒ†ã‚£ãƒªãƒ†ã‚£APIãŒæä¾›ã•れる。メモリ確ä¿é–¢æ•°ã¨ã‚½ãƒ¼ãƒˆé–¢æ•°ã¨æ‹¡å¼µå¯èƒ½ãªãƒ‡ãƒ¼ã‚¿ã¨é…列リストã¨ãƒãƒƒã‚·ãƒ¥ãƒžãƒƒãƒ—ç­‰ã®å®Ÿè£…ã§ã‚る。ãれらを用ã„ã‚‹ã¨ã€C言語ã§ã‚‚Perlã‚„Rubyç­‰ã®ã‚¹ã‚¯ãƒªãƒ—ト言語ã®ã‚ˆã†ãªæ‰‹è»½ã•ã§ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’扱ã†ã“ã¨ãŒã§ãる。

B+木データベースã¯ä¸Šç´šAPIを介ã—ã¦åˆ©ç”¨ã™ã‚‹ã€‚上級APIã¯åŸºæœ¬APIã¨ãƒ¦ãƒ¼ãƒ†ã‚£ãƒªãƒ†ã‚£APIを利用ã—ã¦å®Ÿè£…ã•れる。上級APIも基本APIã‚„æ‹¡å¼µAPIã«é¡žä¼¼ã—ãŸæ›¸å¼ã‚’æŒã¤ã®ã§ã€ä½¿ã„方を覚ãˆã‚‹ã®ã¯å®¹æ˜“ã§ã‚る。

全文検索システムã§åˆ©ç”¨ã•れる転置インデックスを扱ã†ãŸã‚ã«ã€è»¢ç½®APIãŒæä¾›ã•れる。文書群ã®è»¢ç½®ã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹ã‚’å®¹æ˜“ã«æ‰±ã†ã“ã¨ãŒã§ãれã°ã€ã‚¢ãƒ—リケーションã¯ãƒ†ã‚­ã‚¹ãƒˆå‡¦ç†ã‚„自然言語処ç†ã«æ³¨åŠ›ã§ãる。ã“ã®APIã¯æ–‡å­—コードや言語ã«ä¾å­˜ã—ãªã„ã®ã§ã€ãƒ¦ãƒ¼ã‚¶ã®å¤šæ§˜ãªè¦æ±‚ã«å¿œãˆã‚‹å…¨æ–‡æ¤œç´¢ã‚·ã‚¹ãƒ†ãƒ ã‚’実装ã™ã‚‹ã“ã¨ãŒå¯èƒ½ã¨ãªã‚‹ã€‚

QDBMã¯C言語ã®ä»–ã«ã‚‚ã€C++ã€Javaã€PerlãŠã‚ˆã³Rubyã®APIã‚’æä¾›ã™ã‚‹ã€‚C言語ã®APIã«ã¯ã€åŸºæœ¬APIã€æ‹¡å¼µAPIã€NDBM互æ›APIã€GDBM互æ›APIã€ãƒ¦ãƒ¼ãƒ†ã‚£ãƒªãƒ†ã‚£APIã€ä¸Šç´šAPIãŠã‚ˆã³è»¢ç½®APIã®ä¸ƒç¨®é¡žãŒã‚る。å„APIã«å¯¾å¿œã—ãŸã‚³ãƒžãƒ³ãƒ‰ãƒ©ã‚¤ãƒ³ã‚¤ãƒ³ã‚¿ãƒ•ェースも用æ„ã•れã¦ã„る。ãれらã¯ãƒ—ロトタイピングやテストやデãƒãƒƒã‚°ãªã©ã§æ´»èºã™ã‚‹ã€‚C++用APIã¯åŸºæœ¬APIã¨æ‹¡å¼µAPIã¨ä¸Šç´šAPIã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹æ“作関数群をC++ã®ã‚¯ãƒ©ã‚¹æ©Ÿæ§‹ã§ã‚«ãƒ—セル化ã—ãŸã‚‚ã®ã§ã‚る。Java用APIã¯Java Native Interfaceを用ã„ã¦åŸºæœ¬APIã¨æ‹¡å¼µAPIã¨ä¸Šç´šAPIを呼ã³å‡ºã™ã‚‚ã®ã§ã‚る。Perl用APIã¯XS言語を用ã„ã¦åŸºæœ¬APIã¨æ‹¡å¼µAPIã¨ä¸Šç´šAPIを呼ã³å‡ºã™ã‚‚ã®ã§ã‚る。Ruby用APIã¯Rubyã®ãƒ¢ã‚¸ãƒ¥ãƒ¼ãƒ«ã¨ã—ã¦åŸºæœ¬APIã¨æ‹¡å¼µAPIã¨ä¸Šç´šAPIを呼ã³å‡ºã™ã‚‚ã®ã§ã‚る。データベースã®ç®¡ç†ã¨ãƒ•ァイルアップロードã¨å…¨æ–‡æ¤œç´¢ã®ãŸã‚ã®CGIスクリプトもæä¾›ã•れる。

幅広ã„ç§»æ¤æ€§

QDBMã¯ANSI C(C89)ã®è¨˜æ³•ã«å¾“ã„ã€ANSI Cã¾ãŸã¯POSIXã§å®šç¾©ã•れãŸAPIã®ã¿ã‚’用ã„ã¦å®Ÿè£…ã•れる。ã—ãŸãŒã£ã¦ã€ã»ã¨ã‚“ã©ã®UNIXãŠã‚ˆã³ãã®äº’æ›ã‚’ã†ãŸã†OSã§å‹•作ã•ã›ã‚‹ã“ã¨ãŒã§ãる。C言語ã®APIã«é–¢ã—ã¦ã¯ã€å°‘ãªãã¨ã‚‚以下ã®ãƒ—ラットフォームã§å‹•作確èªã•れã¦ã„る。

  • Linux (2.2, 2.4, 2.6) (IA32, IA64, AMD64, PA-RISC, Alpha, PowerPC, M68000, ARM)
  • FreeBSD (4.9, 5.0, 5.1, 5.2, 5.3) (IA32, IA64, SPARC, Alpha)
  • NetBSD (1.6) (IA32)
  • OpenBSD (3.4) (IA32)
  • SunOS (5.6, 5.7, 5.8, 5.9, 5.10) (IA32, SPARC)
  • HP-UX (11.11, 11.23) (IA64, PA-RISC)
  • AIX (5.2) (POWER)
  • Windows (2000, XP) (IA32, IA64, AMD64) (Cygwin, MinGW, Visual C++)
  • Mac OS X (10.2, 10.3, 10.4) (IA32, PowerPC)
  • Tru64 (5.1) (Alpha)
  • RISC OS (5.03) (ARM)

QDBMãŒä½œæˆã—ãŸãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルã¯å‡¦ç†ç³»ã®ãƒã‚¤ãƒˆã‚ªãƒ¼ãƒ€ã«ä¾å­˜ã™ã‚‹ãŒã€ãã®å¯¾ç­–ã¨ã—ã¦ã€ãƒã‚¤ãƒˆã‚ªãƒ¼ãƒ€ã«ä¾å­˜ã—ãªã„å½¢å¼ã®ãƒ‡ãƒ¼ã‚¿ã‚’ダンプã™ã‚‹ãƒ¦ãƒ¼ãƒ†ã‚£ãƒªãƒ†ã‚£ãŒæä¾›ã•れる。


インストール

準備

ソースパッケージを用ã„ã¦QDBMをインストールã™ã‚‹ã«ã¯ã€GCCã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³2.8以é™ã¨ `make' ãŒå¿…è¦ã§ã‚る。

QDBMã®é…布用アーカイブファイルを展開ã—ãŸã‚‰ã€ç”Ÿæˆã•れãŸãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã«å…¥ã£ã¦ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ä½œæ¥­ã‚’行ã†ã€‚

æ™®é€šã®æ‰‹é †

Linuxã¨BSDã¨SunOSã§ã¯ä»¥ä¸‹ã®æ‰‹é †ã«å¾“ã†ã€‚

ビルド環境を設定ã™ã‚‹ã€‚

./configure

プログラムをビルドã™ã‚‹ã€‚

make

プログラムã®è‡ªå·±è¨ºæ–­ãƒ†ã‚¹ãƒˆã‚’行ã†ã€‚

make check

プログラムをインストールã™ã‚‹ã€‚作業㯠`root' ユーザã§è¡Œã†ã€‚

make install

GNU Libtoolを使ã†å ´åˆ

ä¸Šè¨˜ã®æ–¹æ³•ã§ã†ã¾ãã„ã‹ãªã„å ´åˆã€ä»¥ä¸‹ã®æ‰‹é †ã«å¾“ã†ã€‚ã“ã®æ‰‹é †ã«ã¯ã€GNU Libtoolã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³1.5以é™ãŒå¿…è¦ã§ã‚る。

ビルド環境を設定ã™ã‚‹ã€‚

./configure

プログラムをビルドã™ã‚‹ã€‚

make -f LTmakefile

プログラムã®è‡ªå·±è¨ºæ–­ãƒ†ã‚¹ãƒˆã‚’行ã†ã€‚

make -f LTmakefile check

プログラムをインストールã™ã‚‹ã€‚作業㯠`root' ユーザã§è¡Œã†ã€‚

make -f LTmakefile install

çµæžœ

一連ã®ä½œæ¥­ãŒçµ‚ã‚‹ã¨ã€ä»¥ä¸‹ã®ãƒ•ァイルãŒã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•れる。ãã®ä»–ã«ã‚‚ã€ãƒžãƒ‹ãƒ¥ã‚¢ãƒ«ãŒ `/usr/local/man/man1' 㨠`/usr/local/man/man3' ã«ã€ãã‚Œä»¥å¤–ã®æ–‡æ›¸ãŒ `/usr/local/share/qdbm' ã«ã€`pkg-config' 用ã®è¨­å®šãƒ•ァイル㌠`/usr/local/lib/pkgconfig' ã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•れる。

/usr/local/include/depot.h
/usr/local/include/curia.h
/usr/local/include/relic.h
/usr/local/include/hovel.h
/usr/local/include/cabin.h
/usr/local/include/villa.h
/usr/local/include/vista.h
/usr/local/include/odeum.h
/usr/local/lib/libqdbm.a
/usr/local/lib/libqdbm.so.14.14.0
/usr/local/lib/libqdbm.so.14
/usr/local/lib/libqdbm.so
/usr/local/bin/dpmgr
/usr/local/bin/dptest
/usr/local/bin/dptsv
/usr/local/bin/crmgr
/usr/local/bin/crtest
/usr/local/bin/crtsv
/usr/local/bin/rlmgr
/usr/local/bin/rltest
/usr/local/bin/hvmgr
/usr/local/bin/hvtest
/usr/local/bin/cbtest
/usr/local/bin/cbcodec
/usr/local/bin/vlmgr
/usr/local/bin/vltest
/usr/local/bin/vltsv
/usr/local/bin/odmgr
/usr/local/bin/odtest
/usr/local/bin/odidx
/usr/local/bin/qmttest

`libqdbm.so' ã¨å‹•çš„ã«ãƒªãƒ³ã‚¯ã—ãŸãƒ—ログラムを実行ã™ã‚‹éš›ã«ã¯ã€ãƒ©ã‚¤ãƒ–ãƒ©ãƒªã®æ¤œç´¢ãƒ‘ス㫠`/usr/local/lib' ã‚’å«ã‚ã‚‹ã¹ãã§ã‚る。環境変数 `LD_LIBRARY_PATH' ã§ãƒ©ã‚¤ãƒ–ãƒ©ãƒªã®æ¤œç´¢ãƒ‘スを設定ã™ã‚‹ã“ã¨ãŒã§ãる。

QDBMをアンインストールã™ã‚‹ã«ã¯ã€`./configure' ã‚’ã—ãŸå¾Œã®çŠ¶æ…‹ã§ä»¥ä¸‹ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹ã€‚作業㯠`root' ユーザã§è¡Œã†ã€‚

make uninstall

QDBMã®å¤ã„ãƒãƒ¼ã‚¸ãƒ§ãƒ³ãŒã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•れã¦ã„ã‚‹å ´åˆã€ãれをアンインストールã—ã¦ã‹ã‚‰ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ä½œæ¥­ã‚’行ã†ã¹ãã§ã‚る。

C言語以外ã®APIã¨CGIスクリプトã¯ãƒ‡ãƒ•ォルトã§ã¯ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•れãªã„。C++用APIã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«æ–¹æ³•ã«ã¤ã„ã¦ã¯ã€ã‚µãƒ–ディレクトリ `plus' ã«ã‚ã‚‹ `xspex-ja.html' ã‚’å‚ç…§ã™ã‚‹ã“ã¨ã€‚JAVA用APIã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«æ–¹æ³•ã«ã¤ã„ã¦ã¯ã€ã‚µãƒ–ディレクトリ `java' ã«ã‚ã‚‹ `jspex-ja.html' ã‚’å‚ç…§ã™ã‚‹ã“ã¨ã€‚Perl用APIã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«æ–¹æ³•ã«ã¤ã„ã¦ã¯ã€ã‚µãƒ–ディレクトリ `perl' ã«ã‚ã‚‹ `plspex-ja.html' ã‚’å‚ç…§ã™ã‚‹ã“ã¨ã€‚Ruby用APIã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«æ–¹æ³•ã«ã¤ã„ã¦ã¯ã€ã‚µãƒ–ディレクトリ `ruby' ã«ã‚ã‚‹ `rbspex-ja.html' ã‚’å‚ç…§ã™ã‚‹ã“ã¨ã€‚CGIスクリプトã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«æ–¹æ³•ã«ã¤ã„ã¦ã¯ã€ã‚µãƒ–ディレクトリ `cgi' ã«ã‚ã‚‹ `cgispex.html' ã‚’å‚ç…§ã™ã‚‹ã“ã¨ã€‚

RPMç­‰ã®ãƒã‚¤ãƒŠãƒªãƒ‘ッケージを用ã„ã¦ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã‚’行ã†å ´åˆã¯ã€ãれãžã‚Œã®ãƒ‘ッケージマãƒãƒ¼ã‚¸ãƒ£ã®ãƒžãƒ‹ãƒ¥ã‚¢ãƒ«ã‚’å‚ç…§ã™ã‚‹ã“ã¨ã€‚例ãˆã°ã€RPMを用ã„ã‚‹å ´åˆã€ä»¥ä¸‹ã®ã‚ˆã†ãªã‚³ãƒžãƒ³ãƒ‰ã‚’ `root' ユーザã§å®Ÿè¡Œã™ã‚‹ã€‚

rpm -ivh qdbm-1.x.x-x.i386.rpm

Windowsã®å ´åˆ

Windows(Cygwin)ã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã™ã‚‹å ´åˆã€ä»¥ä¸‹ã®æ‰‹é †ã«å¾“ã†ã€‚

ビルド環境を設定ã™ã‚‹ã€‚

./configure

プログラムをビルドã™ã‚‹ã€‚

make win

プログラムã®è‡ªå·±è¨ºæ–­ãƒ†ã‚¹ãƒˆã‚’行ã†ã€‚

make check-win

プログラムをインストールã™ã‚‹ã€‚ãªãŠã€ã‚¢ãƒ³ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã™ã‚‹å ´åˆã¯ `make uninstall-win' ã¨ã™ã‚‹ã€‚

make install-win

Windowsã§ã¯ã€é™çš„ライブラリ `libqdbm.a' ã«åŠ ãˆã¦ã‚¤ãƒ³ãƒãƒ¼ãƒˆãƒ©ã‚¤ãƒ–ラリ `libqdbm.dll.a' ãŒç”Ÿæˆã•れã€å‹•的ライブラリ `libqdbm.so' ç­‰ã®ä»£ã‚りã«ãƒ€ã‚¤ãƒŠãƒŸãƒƒã‚¯ãƒªãƒ³ã‚¯ãƒ©ã‚¤ãƒ–ラリ `qdbm.dll' ãŒç”Ÿæˆã•れる。`qdbm.dll' 㯠`/usr/local/bin' ã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•れる。

Cygwin環境ã§MinGWを用ã„ã¦ãƒ“ルドã™ã‚‹ã«ã¯ã€`make win' ã®ä»£ã‚り㫠`make mingw' を用ã„る。Cygwinã®UNIXエミュレーション層を用ã„ã‚‹å ´åˆã€ç”Ÿæˆã•れるプログラム㯠`cygwin1.dll' ã«ä¾å­˜ã—ãŸã‚‚ã®ã«ãªã‚‹ï¼ˆGNU GPLã®å½±éŸ¿ã‚’å—ã‘る)。MinGWã«ã‚ˆã£ã¦Win32ã®ãƒã‚¤ãƒ†ã‚£ãƒ–DLLã¨ãƒªãƒ³ã‚¯ã•ã›ã‚Œã°ã“ã®å•題を回é¿ã§ãる。

Visual C++を用ã„ã¦ãƒ“ルドã™ã‚‹ã«ã¯ã€`VCmakefile' を編集ã—ã¦ãƒ˜ãƒƒãƒ€ã¨ãƒ©ã‚¤ãƒ–ãƒ©ãƒªã®æ¤œç´¢ãƒ‘スを設定ã—ãŸä¸Šã§ã€`nmake /f VCMakefile' ã¨ã™ã‚Œã°ã‚ˆã„。生æˆã•れ㟠`qdbm.dll' ã¨ãƒªãƒ³ã‚¯ã™ã‚‹ã‚¢ãƒ—リケーションã¯ã€ã‚³ãƒ³ãƒ‘イラ㮠`/MD' ã¾ãŸã¯ `/MDd' オプションを用ã„㦠`msvcrt.dll' ã¨ãƒªãƒ³ã‚¯ã•ã›ã‚‹å¿…è¦ãŒã‚る。詳細設定ã«é–¢ã—ã¦ã¯ `VCmakefile' ã‚’å‚ç…§ã®ã“ã¨ã€‚

Mac OS Xã®å ´åˆ

Mac OS X(Darwin)ã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã™ã‚‹å ´åˆã€ä»¥ä¸‹ã®æ‰‹é †ã«å¾“ã†ã€‚

ビルド環境を設定ã™ã‚‹ã€‚

./configure

プログラムをビルドã™ã‚‹ã€‚

make mac

プログラムã®è‡ªå·±è¨ºæ–­ãƒ†ã‚¹ãƒˆã‚’行ã†ã€‚

make check-mac

プログラムをインストールã™ã‚‹ã€‚ãªãŠã€ã‚¢ãƒ³ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã™ã‚‹å ´åˆã¯ `make uninstall-mac' ã¨ã™ã‚‹ã€‚

make install-mac

Mac OS Xã§ã¯ã€`libqdbm.so' ç­‰ã®ä»£ã‚り㫠`libqdbm.dylib' ç­‰ãŒç”Ÿæˆã•ã‚Œã‚‹ã€‚ãƒ©ã‚¤ãƒ–ãƒ©ãƒªã®æ¤œç´¢ãƒ‘ã‚¹ã®æŒ‡å®šã¯ç’°å¢ƒå¤‰æ•° `DYLD_LIBRARY_PATH' ã§è¡Œã†ã“ã¨ãŒã§ãる。

HP-UXã®å ´åˆ

HP-UXã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã™ã‚‹å ´åˆã€ä»¥ä¸‹ã®æ‰‹é †ã«å¾“ã†ã€‚

ビルド環境を設定ã™ã‚‹ã€‚

./configure

プログラムをビルドã™ã‚‹ã€‚

make hpux

プログラムã®è‡ªå·±è¨ºæ–­ãƒ†ã‚¹ãƒˆã‚’行ã†ã€‚

make check-hpux

プログラムをインストールã™ã‚‹ã€‚ãªãŠã€ã‚¢ãƒ³ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã™ã‚‹å ´åˆã¯ `make uninstall-hpux' ã¨ã™ã‚‹ã€‚

make install-hpux

HP-UXã§ã¯ã€`libqdbm.so' ç­‰ã®ä»£ã‚り㫠`libqdbm.sl' ãŒç”Ÿæˆã•ã‚Œã‚‹ã€‚ãƒ©ã‚¤ãƒ–ãƒ©ãƒªã®æ¤œç´¢ãƒ‘ã‚¹ã®æŒ‡å®šã¯ç’°å¢ƒå¤‰æ•° `SHLIB_PATH' ã§è¡Œã†ã“ã¨ãŒã§ãる。

RISC OSã®å ´åˆ

RISC OSã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã™ã‚‹å ´åˆã€ä»¥ä¸‹ã®æ‰‹é †ã«å¾“ã†ã€‚

プログラムをビルドã™ã‚‹ã€‚デフォルトã§ã¯ã‚³ãƒ³ãƒ‘イラ㫠`cc' を用ã„るよã†ã«ãªã£ã¦ã„ã‚‹ãŒã€`gcc' を用ã„ãŸã‘れ㰠`CC=gcc' ã¨ã„ã†å¼•数を加ãˆã‚Œã°ã‚ˆã„。

make -f RISCmakefile

一連ã®ä½œæ¥­ãŒçµ‚ã‚‹ã¨ã€`libqdbm' ã¨ã„ã†ãƒ©ã‚¤ãƒ–ラリファイル㨠`dpmgr' ç­‰ã®ã‚³ãƒžãƒ³ãƒ‰ãŒç”Ÿæˆã•れる。ãれらã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«æ–¹æ³•ã¯å®šç¾©ã•れã¦ã„ãªã„ã®ã§ã€æ‰‹å‹•ã§ä»»æ„ã®å ´æ‰€ã«ã‚³ãƒ”ーã—ã¦ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã™ã‚‹ã“ã¨ã€‚`depot.h' ç­‰ã®ãƒ˜ãƒƒãƒ€ãƒ•ã‚¡ã‚¤ãƒ«ã‚‚åŒæ§˜ã«æ‰‹å‹•ã§ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã™ã‚‹ã“ã¨ã€‚

詳細設定

`./configure' を実行ã™ã‚‹éš›ã«ä»¥ä¸‹ã®ã‚ªãƒ—ション引数を指定ã™ã‚‹ã“ã¨ã§ã€ãƒ“ルド方法ã®è©³ç´°ãªè¨­å®šã‚’行ã†ã“ã¨ãŒã§ãる。

  • --enable-debug : デãƒãƒƒã‚°ç”¨ã«ãƒ“ルドã™ã‚‹ã€‚デãƒãƒƒã‚°ã‚·ãƒ³ãƒœãƒ«ã‚’有効化ã—ã€æœ€é©åŒ–を行ã‚ãšã€é™çš„ã«ãƒªãƒ³ã‚¯ã™ã‚‹ã€‚
  • --enable-devel : 開発用ã«ãƒ“ルドã™ã‚‹ã€‚デãƒãƒƒã‚°ã‚·ãƒ³ãƒœãƒ«ã‚’有効化ã—ã€æœ€é©åŒ–を行ã„ã€å‹•çš„ã«ãƒªãƒ³ã‚¯ã™ã‚‹ã€‚
  • --enable-stable : 安定版ã®ãƒªãƒªãƒ¼ã‚¹ç”¨ã«ãƒ“ルドã™ã‚‹ã€‚ä¿å®ˆçš„ãªæœ€é©åŒ–を行ã„ã€å‹•çš„ã«ãƒªãƒ³ã‚¯ã™ã‚‹ã€‚
  • --enable-pthread : POSIXスレッドを用ã„ã€ã‚°ãƒ­ãƒ¼ãƒãƒ«å¤‰æ•°ã‚’スレッド固有データã¨ã—ã¦æ‰±ã†ã€‚
  • --disable-lock : ファイルロッキングãŒå®Ÿè£…ã•れã¦ã„ãªã„環境用ã«ãƒ“ルドã™ã‚‹ã€‚
  • --disable-mmap : メモリマッピングãŒå®Ÿè£…ã•れã¦ã„ãªã„環境用ã«ãƒ“ルドã™ã‚‹ã€‚
  • --enable-zlib : ZLIBã«ã‚ˆã‚‹B+木ã¨è»¢ç½®ã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹ã®ãƒ¬ã‚³ãƒ¼ãƒ‰åœ§ç¸®ã‚’機能ã•ã›ã‚‹ã€‚
  • --enable-lzo : LZOã«ã‚ˆã‚‹B+木ã¨è»¢ç½®ã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹ã®ãƒ¬ã‚³ãƒ¼ãƒ‰åœ§ç¸®ã‚’機能ã•ã›ã‚‹ã€‚
  • --enable-bzip : BZIP2ã«ã‚ˆã‚‹B+木ã¨è»¢ç½®ã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹ã®ãƒ¬ã‚³ãƒ¼ãƒ‰åœ§ç¸®ã‚’機能ã•ã›ã‚‹ã€‚
  • --enable-iconv : ICONVã«ã‚ˆã‚‹æ–‡å­—コード変æ›ãƒ¦ãƒ¼ãƒ†ã‚£ãƒªãƒ†ã‚£ã‚’機能ã•ã›ã‚‹ã€‚

通常ã€QDBMã¨ãã®ã‚¢ãƒ—リケーション㯠`libqdbm.*' 以外ã®éžæ¨™æº–ã®ãƒ©ã‚¤ãƒ–ラリã«ã¯ä¾å­˜ã—ãªã„ã§ãƒ“ルドã™ã‚‹ã“ã¨ãŒã§ãる。ãŸã ã—ã€POSIXスレッドを有効ã«ã—ãŸå ´åˆã¯ `libpthread.*' ã«ä¾å­˜ã—ã€ZLIBを有効ã«ã—ãŸå ´åˆã¯ `libz.*' ã«ä¾å­˜ã—ã€LZOを有効ã«ã—ãŸå ´åˆã¯ `liblzo2.*' ã«ä¾å­˜ã—ã€BZIP2を有効ã«ã—ãŸå ´åˆã¯ `libbz2.*' ã«ä¾å­˜ã—ã€ICONVを有効ã«ã—ãŸå ´åˆã¯ `libiconv.*' ã«ä¾å­˜ã™ã‚‹ã‚ˆã†ã«ãªã‚‹ã€‚

LZOã®ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã¯GNU GPLãªã®ã§ã€`liblzo2.*' ã¨ãƒªãƒ³ã‚¯ã—ãŸã‚¢ãƒ—リケーションã¯GNU GPLã®åˆ¶ç´„ã‚’å—ã‘ã‚‹ã“ã¨ã«æ³¨æ„ã™ã‚‹ã“ã¨ã€‚


Depot: 基本API

概è¦

Depotã¯QDBMã®åŸºæœ¬APIã§ã‚る。QDBMãŒæä¾›ã™ã‚‹ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ç®¡ç†æ©Ÿèƒ½ã®ã»ã¼å…¨ã¦ãŒDepotã«ã‚ˆã£ã¦å®Ÿè£…ã•れる。ãã®ä»–ã®APIã¯Depotã®ãƒ©ãƒƒãƒ‘ーã«ã™ãŽãªã„。ã—ãŸãŒã£ã¦ã€QDBMã®APIã®ä¸­ã§DepotãŒæœ€ã‚‚高速ã«å‹•作ã™ã‚‹ã€‚

Depotを使ã†ãŸã‚ã«ã¯ã€`depot.h' 㨠`stdlib.h' をインクルードã™ã¹ãã§ã‚る。通常ã€ã‚½ãƒ¼ã‚¹ãƒ•ァイルã®å†’頭付近ã§ä»¥ä¸‹ã®è¨˜è¿°ã‚’行ã†ã€‚

#include <depot.h>
#include <stdlib.h>

Depotã§ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’扱ã†éš›ã«ã¯ã€`DEPOT' åž‹ã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’ãƒãƒ³ãƒ‰ãƒ«ã¨ã—ã¦ç”¨ã„る。ã“れã¯ã€`stdio.h' ã®å„種ルーãƒãƒ³ãŒãƒ•ァイル入出力㫠`FILE' åž‹ã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’用ã„ã‚‹ã®ã«ä¼¼ã¦ã„る。ãƒãƒ³ãƒ‰ãƒ«ã¯ã€é–¢æ•° `dpopen' ã§é–‹ãã€é–¢æ•° `dpclose' ã§é–‰ã˜ã‚‹ã€‚ãƒãƒ³ãƒ‰ãƒ«ã®ãƒ¡ãƒ³ãƒã‚’直接å‚ç…§ã™ã‚‹ã“ã¨ã¯æŽ¨å¥¨ã•れãªã„。データベースã«è‡´å‘½çš„ãªã‚¨ãƒ©ãƒ¼ãŒèµ·ããŸå ´åˆã¯ã€ä»¥å¾Œãã®ãƒãƒ³ãƒ‰ãƒ«ã«å¯¾ã™ã‚‹ `dpclose' を除ãå…¨ã¦ã®æ“作ã¯ä½•ã‚‚ã›ãšã«ã‚¨ãƒ©ãƒ¼ã‚’è¿”ã™ã€‚ã²ã¨ã¤ã®ãƒ—ロセスã§è¤‡æ•°ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ã‚¡ã‚¤ãƒ«ã‚’åŒæ™‚ã«åˆ©ç”¨ã™ã‚‹ã“ã¨ã¯å¯èƒ½ã§ã‚ã‚‹ãŒã€åŒã˜ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルã®è¤‡æ•°ã®ãƒãƒ³ãƒ‰ãƒ«ã‚’利用ã—ã¦ã¯ãªã‚‰ãªã„。

API

外部変数 `dpversion' ã¯ãƒãƒ¼ã‚¸ãƒ§ãƒ³æƒ…å ±ã®æ–‡å­—列ã§ã‚る。

extern const char *dpversion;
ã“ã®å¤‰æ•°ã®æŒ‡ã™é ˜åŸŸã¯æ›¸ãè¾¼ã¿ç¦æ­¢ã§ã‚る。

外部変数 `dpecode' ã«ã¯ç›´å‰ã®ã‚¨ãƒ©ãƒ¼ã‚³ãƒ¼ãƒ‰ãŒè¨˜éŒ²ã•れる。エラーコードã®è©³ç´°ã«ã¤ã„ã¦ã¯ `depot.h' ã‚’å‚ç…§ã™ã‚‹ã“ã¨ã€‚

extern int dpecode;
ã“ã®å¤‰æ•°ã®åˆæœŸå€¤ã¯ `DP_ENOERR' ã§ã‚る。ãã®ä»–ã®å€¤ã¨ã—ã¦ã€`DP_EFATAL'ã€`DP_EMODE'ã€`DP_EBROKEN'ã€`DP_EKEEP'ã€`DP_ENOITEM'ã€`DP_EALLOC'ã€`DP_EMAP'ã€`DP_EOPEN'ã€`DP_ECLOSE'ã€`DP_ETRUNC'ã€`DP_ESYNC'ã€`DP_ESTAT'ã€`DP_ESEEK'ã€`DP_EREAD'ã€`DP_EWRITE'ã€`DP_ELOCK'ã€`DP_EUNLINK'ã€`DP_EMKDIR'ã€`DP_ERMDIR' ãŠã‚ˆã³ `DP_EMISC' ãŒã‚る。

エラーコードã«å¯¾å¿œã™ã‚‹ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸æ–‡å­—列を得るã«ã¯ã€é–¢æ•° `dperrmsg' を用ã„る。

const char *dperrmsg(int ecode);
`ecode' ã¯ã‚¨ãƒ©ãƒ¼ã‚³ãƒ¼ãƒ‰ã‚’指定ã™ã‚‹ã€‚戻り値ã¯ã‚¨ãƒ©ãƒ¼ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã®æ–‡å­—列ã§ã‚りã€ãã®é ˜åŸŸã¯æ›¸ãè¾¼ã¿ç¦æ­¢ã§ã‚る。

データベースã®ãƒãƒ³ãƒ‰ãƒ«ã‚’作æˆã™ã‚‹ã«ã¯ã€é–¢æ•° `dpopen' を用ã„る。

DEPOT *dpopen(const char *name, int omode, int bnum);
`name' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルã®åå‰ã‚’指定ã™ã‚‹ã€‚`omode' ã¯æŽ¥ç¶šãƒ¢ãƒ¼ãƒ‰ã‚’æŒ‡å®šã—ã€`DP_OREADER' ãªã‚‰ãƒªãƒ¼ãƒ€ã€`DP_OWRITER' ãªã‚‰ãƒ©ã‚¤ã‚¿ã¨ãªã‚‹ã€‚`DP_OWRITER' ã®å ´åˆã€`DP_OCREAT' ã¾ãŸã¯ `DP_OTRUNC' ã¨ã®ãƒ“ット論ç†å’Œã«ã™ã‚‹ã“ã¨ãŒã§ãる。`DP_OCREAT' ã¯ãƒ•ァイルãŒç„¡ã„å ´åˆã«æ–°è¦ä½œæˆã™ã‚‹ã“ã¨ã‚’指示ã—ã€`DP_OTRUNC' ã¯ãƒ•ァイルãŒå­˜åœ¨ã—ã¦ã‚‚作り直ã™ã“ã¨ã‚’指示ã™ã‚‹ã€‚`DP_OREADER' 㨠`DP_OWRITER' ã®ä¸¡æ–¹ã§ `DP_ONOLCK' ã¾ãŸã¯ `DP_OLCKNB' ã¨ã®ãƒ“ット論ç†å’Œã«ã™ã‚‹ã“ã¨ãŒã§ãã‚‹ãŒã€å‰è€…ã¯ãƒ•ァイルロックをã‹ã‘ãšã«ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’é–‹ãã“ã¨ã‚’指示ã—ã€å¾Œè€…ã¯ãƒ–ロックã›ãšã«ãƒ­ãƒƒã‚¯ã‚’ã‹ã‘ã‚‹ã“ã¨ã‚’指示ã™ã‚‹ã€‚`DP_OCREAT' 㯠`DP_OSPARSE' ã¨ã®ãƒ“ット論ç†å’Œã«ã™ã‚‹ã“ã¨ãŒã§ãã‚‹ãŒã€ãれã¯ç”Ÿæˆã•れるファイルをスパースã«ã™ã‚‹ã“ã¨ã‚’指示ã™ã‚‹ã€‚`bnum' ã¯ãƒã‚±ãƒƒãƒˆé…列ã®è¦ç´ æ•°ã®ç›®å®‰ã‚’指定ã™ã‚‹ãŒã€0 以下ãªã‚‰ãƒ‡ãƒ•ォルト値ãŒä½¿ã‚れる。ãƒã‚±ãƒƒãƒˆé…列ã®è¦ç´ æ•°ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’作æˆã™ã‚‹æ™‚ã«æ±ºã‚ã‚‰ã‚Œã€æœ€é©åŒ–ä»¥å¤–ã®æ‰‹æ®µã§å¤‰æ›´ã™ã‚‹ã“ã¨ã¯ã§ããªã„。ãƒã‚±ãƒƒãƒˆé…列ã®è¦ç´ æ•°ã¯ã€æ ¼ç´ã™ã‚‹ãƒ¬ã‚³ãƒ¼ãƒ‰æ•°ã®åŠåˆ†ã‹ã‚‰4å€ç¨‹åº¦ã«ã™ã‚‹ã®ãŒã‚ˆã„。戻り値ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã§ã‚ã‚‹ã‹ã€ã‚¨ãƒ©ãƒ¼ãªã‚‰ `NULL' ã§ã‚ã‚‹ã€‚ãƒ©ã‚¤ã‚¿ï¼ˆèª­ã¿æ›¸ã両用モード)ã§ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルを開ãéš›ã«ã¯ãã®ãƒ•ァイルã«å¯¾ã—ã¦æŽ’ä»–ãƒ­ãƒƒã‚¯ãŒã‹ã‘られã€ãƒªãƒ¼ãƒ€ï¼ˆèª­ã¿è¾¼ã¿å°‚用モード)ã§é–‹ãéš›ã«ã¯å…±æœ‰ãƒ­ãƒƒã‚¯ãŒã‹ã‘られる。ãã®éš›ã«ã¯è©²å½“ã®ãƒ­ãƒƒã‚¯ãŒã‹ã‘られるã¾ã§åˆ¶å¾¡ãŒãƒ–ロックã™ã‚‹ã€‚`DP_ONOLCK' を使ã†å ´åˆã€ã‚¢ãƒ—ãƒªã‚±ãƒ¼ã‚·ãƒ§ãƒ³ãŒæŽ’ä»–åˆ¶å¾¡ã®è²¬ä»»ã‚’è² ã†ã€‚

データベースã¨ã®æŽ¥ç¶šã‚’é–‰ã˜ã¦ãƒãƒ³ãƒ‰ãƒ«ã‚’破棄ã™ã‚‹ã«ã¯ã€é–¢æ•° `dpclose' を用ã„る。

int dpclose(DEPOT *depot);
`depot' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰çœŸã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰å½ã§ã‚ã‚‹ã€‚ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®æ›´æ–°å†…容ã¯ã€æŽ¥ç¶šã‚’é–‰ã˜ãŸæ™‚点ã§åˆã‚ã¦ãƒ•ァイルã¨åŒæœŸã•れる。ライタã§ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’é–‹ã„ãŸå ´åˆã€é©åˆ‡ã«æŽ¥ç¶šã‚’é–‰ã˜ãªã„ã¨ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãŒç ´å£Šã•れる。閉ã˜ãŸãƒãƒ³ãƒ‰ãƒ«ã®é ˜åŸŸã¯è§£æ”¾ã•れるã®ã§ã€ä»¥å¾Œã¯åˆ©ç”¨ã§ããªããªã‚‹ã€‚

レコードを追加ã™ã‚‹ã«ã¯ã€é–¢æ•° `dpput' を用ã„る。

int dpput(DEPOT *depot, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int dmode);
`depot' ã¯ãƒ©ã‚¤ã‚¿ã§æŽ¥ç¶šã—ãŸãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`kbuf' ã¯ã‚­ãƒ¼ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`ksiz' ã¯ã‚­ãƒ¼ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã‹ã€è² æ•°ãªã‚‰ `strlen(kbuf)' ã®å€¤ã¨ãªã‚‹ã€‚`vbuf' ã¯å€¤ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`vsiz' ã¯å€¤ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã‹ã€è² æ•°ãªã‚‰ `strlen(vbuf)' ã®å€¤ã¨ãªã‚‹ã€‚`dmode' ã¯ã‚­ãƒ¼ãŒæ—¢å­˜ãƒ¬ã‚³ãƒ¼ãƒ‰ã¨é‡è¤‡ã—ãŸéš›ã®åˆ¶å¾¡ã‚’指定ã™ã‚‹ã€‚`DP_DOVER' ã¯æ—¢å­˜ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã®å€¤ã‚’上書ãã—ã€`DP_DKEEP' ã¯æ—¢å­˜ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’残ã—ã¦ã‚¨ãƒ©ãƒ¼ã‚’è¿”ã—ã€`DP_DCAT' ã¯æŒ‡å®šã•れãŸå€¤ã‚’既存ã®å€¤ã®æœ«å°¾ã«åŠ ãˆã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰çœŸã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰å½ã§ã‚る。

レコードを削除ã™ã‚‹ã«ã¯ã€é–¢æ•° `dpout' を用ã„る。

int dpout(DEPOT *depot, const char *kbuf, int ksiz);
`depot' ã¯ãƒ©ã‚¤ã‚¿ã§æŽ¥ç¶šã—ãŸãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`kbuf' ã¯ã‚­ãƒ¼ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`ksiz' ã¯ã‚­ãƒ¼ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã‹ã€è² æ•°ãªã‚‰ `strlen(kbuf)' ã®å€¤ã¨ãªã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰çœŸã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰å½ã§ã‚る。該当ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ãŒãªã„å ´åˆã‚‚å½ã‚’è¿”ã™ã€‚

レコードをå–å¾—ã™ã‚‹ã«ã¯ã€é–¢æ•° `dpget' を用ã„る。

char *dpget(DEPOT *depot, const char *kbuf, int ksiz, int start, int max, int *sp);
`depot' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`kbuf' ã¯ã‚­ãƒ¼ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`ksiz' ã¯ã‚­ãƒ¼ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã‹ã€è² æ•°ãªã‚‰ `strlen(kbuf)' ã®å€¤ã¨ãªã‚‹ã€‚`start' ã¯å€¤ã®é ˜åŸŸã‹ã‚‰æŠ½å‡ºã™ã‚‹æœ€åˆã®ãƒã‚¤ãƒˆã®ã‚ªãƒ•セットを指定ã™ã‚‹ã€‚`max' ã¯å€¤ã®é ˜åŸŸã‹ã‚‰æŠ½å‡ºã™ã‚‹ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã‹ã€è² æ•°ãªã‚‰ç„¡åˆ¶é™ã¨ãªã‚‹ã€‚`sp' ㌠`NULL' ã§ãªã‘れã°ã€ãã®å‚ç…§å…ˆã«æŠ½å‡ºã—ãŸé ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’æ ¼ç´ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰å€¤ã‚’æ ¼ç´ã—ãŸé ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰ `NULL' ã§ã‚る。該当ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ãŒãªã„å ´åˆã‚‚ `NULL' ã‚’è¿”ã™ã€‚å–り出ãã†ã¨ã—ãŸå€¤ã®ã‚µã‚¤ã‚ºãŒ `start' よりå°ã•ã‹ã£ãŸå ´åˆã«ã¯è©²å½“ã¨ã¿ãªã•ãªã„。戻り値ã®é ˜åŸŸã¯ã€å®Ÿéš›ã«ã¯1ãƒã‚¤ãƒˆå¤šã確ä¿ã—ã¦çµ‚端文字ãŒç½®ã‹ã‚Œã‚‹ã®ã§ã€æ–‡å­—列ã¨ã—ã¦åˆ©ç”¨ã§ãる。戻り値ã®é ˜åŸŸã¯ `malloc' ã§ç¢ºä¿ã•れるã®ã§ã€ä¸è¦ã«ãªã£ãŸã‚‰ `free' ã§è§£æ”¾ã™ã‚‹ã¹ãã§ã‚る。

レコードをå–å¾—ã—ã¦ãƒãƒƒãƒ•ã‚¡ã«æ›¸ã込むã«ã¯ã€é–¢æ•° `dpgetwb' を用ã„る。

int dpgetwb(DEPOT *depot, const char *kbuf, int ksiz, int start, int max, char *vbuf);
`depot' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`kbuf' ã¯ã‚­ãƒ¼ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`ksiz' ã¯ã‚­ãƒ¼ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã‹ã€è² æ•°ãªã‚‰ `strlen(kbuf)' ã®å€¤ã¨ãªã‚‹ã€‚`start' ã¯å€¤ã®é ˜åŸŸã‹ã‚‰æŠ½å‡ºã™ã‚‹æœ€åˆã®ãƒã‚¤ãƒˆã®ã‚ªãƒ•セットを指定ã™ã‚‹ã€‚`max' ã¯å€¤ã®é ˜åŸŸã‹ã‚‰æŠ½å‡ºã™ã‚‹ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã€‚ãã‚Œã¯æ›¸ãè¾¼ã¿ç”¨ã®ãƒãƒƒãƒ•ã‚¡ã®ã‚µã‚¤ã‚ºä»¥ä¸‹ã§ã‚ã‚‹å¿…è¦ãŒã‚る。`vbuf' ã¯æŠ½å‡ºã—ãŸãƒ‡ãƒ¼ã‚¿ã‚’書ã込むãƒãƒƒãƒ•ã‚¡ã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰ãƒãƒƒãƒ•ã‚¡ã«æ›¸ãè¾¼ã¾ã‚ŒãŸãƒ‡ãƒ¼ã‚¿ã®ã‚µã‚¤ã‚ºã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰ -1 ã§ã‚る。該当ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ãŒãªã„å ´åˆã‚‚ -1 ã‚’è¿”ã™ã€‚å–り出ãã†ã¨ã—ãŸå€¤ã®ã‚µã‚¤ã‚ºãŒ `start' よりå°ã•ã‹ã£ãŸå ´åˆã«ã¯è©²å½“ã¨ã¿ãªã•ãªã„。書ãè¾¼ã¿ç”¨ãƒãƒƒãƒ•ã‚¡ã®æœ«å°¾ã«çµ‚端文字ãŒè¿½åŠ ã•れãªã„ã“ã¨ã«æ³¨æ„ã™ã¹ãã§ã‚る。

レコードã®å€¤ã®ã‚µã‚¤ã‚ºã‚’å–å¾—ã™ã‚‹ã«ã¯ã€é–¢æ•° `dpvsiz' を用ã„る。

int dpvsiz(DEPOT *depot, const char *kbuf, int ksiz);
`depot' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`kbuf' ã¯ã‚­ãƒ¼ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`ksiz' ã¯ã‚­ãƒ¼ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã‹ã€è² æ•°ãªã‚‰ `strlen(kbuf)' ã®å€¤ã¨ãªã‚‹ã€‚戻り値ã¯è©²å½“レコードã®å€¤ã®ã‚µã‚¤ã‚ºã§ã‚ã‚‹ãŒã€è©²å½“ãŒãªã„å ´åˆã‚„エラーã®å ´åˆã¯ -1 ã§ã‚る。ã“ã®é–¢æ•°ã¯ãƒ¬ã‚³ãƒ¼ãƒ‰ã®æœ‰ç„¡ã‚’調ã¹ã‚‹ã®ã«ã‚‚便利ã§ã‚る。`dpget' ã¨é•ã£ã¦å®Ÿãƒ‡ãƒ¼ã‚¿ã‚’読ã¿è¾¼ã¾ãªã„ã®ã§åŠ¹çŽ‡ãŒã‚ˆã„。

データベースã®ã‚¤ãƒ†ãƒ¬ãƒ¼ã‚¿ã‚’åˆæœŸåŒ–ã™ã‚‹ã«ã¯ã€é–¢æ•° `dpiterinit' を用ã„る。

int dpiterinit(DEPOT *depot);
`depot' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰çœŸã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰å½ã§ã‚る。イテレータã¯ã€ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«æ ¼ç´ã•れãŸå…¨ã¦ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’å‚ç…§ã™ã‚‹ãŸã‚ã«ç”¨ã„られる。

データベースã®ã‚¤ãƒ†ãƒ¬ãƒ¼ã‚¿ã‹ã‚‰æ¬¡ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã®ã‚­ãƒ¼ã‚’å–り出ã™ã«ã¯ã€é–¢æ•° `dpiternext' を用ã„る。

char *dpiternext(DEPOT *depot, int *sp);
`depot' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`sp' ㌠`NULL' ã§ãªã‘れã°ã€ãã®å‚ç…§å…ˆã«æŠ½å‡ºã—ãŸé ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’æ ¼ç´ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰ã‚­ãƒ¼ã‚’æ ¼ç´ã—ãŸé ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰ `NULL' ã§ã‚ã‚‹ã€‚ã‚¤ãƒ†ãƒ¬ãƒ¼ã‚¿ãŒæœ€å¾Œã¾ã§ãã¦è©²å½“ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ãŒãªã„å ´åˆã‚‚ `NULL' ã‚’è¿”ã™ã€‚戻り値ã®é ˜åŸŸã¯ã€å®Ÿéš›ã«ã¯1ãƒã‚¤ãƒˆå¤šã確ä¿ã—ã¦çµ‚端文字ãŒç½®ã‹ã‚Œã‚‹ã®ã§ã€æ–‡å­—列ã¨ã—ã¦åˆ©ç”¨ã§ãる。戻り値ã®é ˜åŸŸã¯ `malloc' ã§ç¢ºä¿ã•れるã®ã§ã€ä¸è¦ã«ãªã£ãŸã‚‰ `free' ã§è§£æ”¾ã™ã‚‹ã¹ãã§ã‚る。ã“ã®é–¢æ•°ã‚’繰り返ã—ã¦å‘¼ã¶ã“ã¨ã«ã‚ˆã£ã¦å…¨ã¦ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’一度ãšã¤å‚ç…§ã™ã‚‹ã“ã¨ãŒã§ãる。ãŸã ã—ã€ç¹°ã‚Šè¿”ã—ã®é–“ã«ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®æ›´æ–°ãŒã‚ã£ãŸå ´åˆã¯ãã®é™ã‚Šã§ã¯ãªã„。ãªãŠã€å–り出ã™ãƒ¬ã‚³ãƒ¼ãƒ‰ã®é †åºã¯åˆ¶å¾¡ã§ããšã€æ ¼ç´ã—ãŸé †ç•ªã§ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’å–り出ã›ã‚‹ã¨ã¯é™ã‚‰ãªã„。

データベースã®ã‚¢ãƒ©ã‚¤ãƒ³ãƒ¡ãƒ³ãƒˆã‚’設定ã™ã‚‹ã«ã¯ã€é–¢æ•° `dpsetalign' を用ã„る。

int dpsetalign(DEPOT *depot, int align);
`depot' ã¯ãƒ©ã‚¤ã‚¿ã§æŽ¥ç¶šã—ãŸãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`align' ã¯ã‚¢ãƒ©ã‚¤ãƒ³ãƒ¡ãƒ³ãƒˆã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰çœŸã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰å½ã§ã‚る。アラインメントを設定ã—ã¦ãŠãã¨ã€ãƒ¬ã‚³ãƒ¼ãƒ‰ã®ä¸Šæ›¸ãã‚’é »ç¹ã«ã™ã‚‹å ´åˆã®å‡¦ç†åŠ¹çŽ‡ãŒè‰¯ããªã‚‹ã€‚アラインメントã«ã¯ã€ä¸€é€£ã®æ›´æ–°æ“作をã—ãŸå¾Œã®çŠ¶æ…‹ã§ã®æ¨™æº–çš„ãªå€¤ã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã®ãŒã‚ˆã„ã€‚ã‚¢ãƒ©ã‚¤ãƒ³ãƒ¡ãƒ³ãƒˆãŒæ­£æ•°ã®å ´åˆã€ãƒ¬ã‚³ãƒ¼ãƒ‰ã®é ˜åŸŸã®ã‚µã‚¤ã‚ºãŒã‚¢ãƒ©ã‚¤ãƒ³ãƒ¡ãƒ³ãƒˆã®å€æ•°ã«ãªã‚‹ã‚ˆã†ã«ãƒ‘ディングãŒã¨ã‚‰ã‚Œã‚‹ã€‚アラインメントãŒè² æ•°ã®å ´åˆã€`vsiz' を値ã®ã‚µã‚¤ã‚ºã¨ã—ã¦ã€ãƒ‘ディングã®ã‚µã‚¤ã‚ºã¯ `(vsiz / pow(2, abs(align) - 1))' ã¨ã—ã¦ç®—出ã•れる。アラインメントã®è¨­å®šã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«ä¿å­˜ã•れãªã„ã®ã§ã€ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’é–‹ãåº¦ã«æŒ‡å®šã™ã‚‹å¿…è¦ãŒã‚る。

データベースã®ãƒ•リーブロックプールã®ã‚µã‚¤ã‚ºè¨­å®šã™ã‚‹ã«ã¯ã€é–¢æ•° `dpsetfbpsiz' を用ã„る。

int dpsetfbpsiz(DEPOT *depot, int size);
`depot' ã¯ãƒ©ã‚¤ã‚¿ã§æŽ¥ç¶šã—ãŸãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`size' ã¯ãƒ•リーブロックプールã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰çœŸã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰å½ã§ã‚る。フリーブロックプールã®ãƒ‡ãƒ•ォルトã®ã‚µã‚¤ã‚ºã¯16ã§ã‚る。サイズをより大ããã™ã‚‹ã¨ã€ãƒ¬ã‚³ãƒ¼ãƒ‰ã®ä¸Šæ›¸ãを繰り返ã™éš›ã®ç©ºé–“効率ã¯ä¸ŠãŒã‚‹ãŒã€æ™‚間効率ãŒä¸‹ãŒã‚‹ã€‚

データベースを更新ã—ãŸå†…容をファイルã¨ãƒ‡ãƒã‚¤ã‚¹ã«åŒæœŸã•ã›ã‚‹ã«ã¯ã€é–¢æ•° `dpsync' を用ã„る。

int dpsync(DEPOT *depot);
`depot' ã¯ãƒ©ã‚¤ã‚¿ã§æŽ¥ç¶šã—ãŸãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰çœŸã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰å½ã§ã‚る。ã“ã®é–¢æ•°ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’é–‰ã˜ãªã„ã†ã¡ã«åˆ¥ãƒ—ロセスã«ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルを利用ã•ã›ã‚‹å ´åˆã«å½¹ç«‹ã¤ã€‚

データベースを最é©åŒ–ã™ã‚‹ã«ã¯ã€é–¢æ•° `dpoptimize' を用ã„る。

int dpoptimize(DEPOT *depot, int bnum);
`depot' ã¯ãƒ©ã‚¤ã‚¿ã§æŽ¥ç¶šã—ãŸãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`bnum' ã¯æ–°ãŸãªãƒã‚±ãƒƒãƒˆé…列ã®è¦ç´ æ•°ã‚’指定ã™ã‚‹ãŒã€0 以下ãªã‚‰ç¾åœ¨ã®ãƒ¬ã‚³ãƒ¼ãƒ‰æ•°ã«æœ€é©ãªå€¤ãŒæŒ‡å®šã•ã‚Œã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰çœŸã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰å½ã§ã‚る。レコードを削除ã—ãŸã‚Šã€ç½®æ›ãƒ¢ãƒ¼ãƒ‰ã‚„連çµãƒ¢ãƒ¼ãƒ‰ã§æ›¸ãè¾¼ã¿ã‚’繰り返ã—ãŸã‚Šã™ã‚‹å ´åˆã¯ã€ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹å†…ã«ä¸è¦ãªé ˜åŸŸãŒè“„ç©ã™ã‚‹ãŒã€ã“ã®é–¢æ•°ã¯ãれを解消ã™ã‚‹ã®ã«å½¹ç«‹ã¤ã€‚

データベースã®åå‰ã‚’å¾—ã‚‹ã«ã¯ã€é–¢æ•° `dpname' を用ã„る。

char *dpname(DEPOT *depot);
`depot' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰åå‰ã‚’æ ¼ç´ã—ãŸé ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰ `NULL' ã§ã‚る。戻り値ã®é ˜åŸŸã¯ `malloc' ã§ç¢ºä¿ã•れるã®ã§ã€ä¸è¦ã«ãªã£ãŸã‚‰ `free' ã§è§£æ”¾ã™ã‚‹ã¹ãã§ã‚る。

データベースファイルã®ã‚µã‚¤ã‚ºã‚’å¾—ã‚‹ã«ã¯ã€é–¢æ•° `dpfsiz' を用ã„る。

int dpfsiz(DEPOT *depot);
`depot' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルã®ã‚µã‚¤ã‚ºã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰ -1 ã§ã‚る。

データベースã®ãƒã‚±ãƒƒãƒˆé…列ã®è¦ç´ æ•°ã‚’å¾—ã‚‹ã«ã¯ã€é–¢æ•° `dpbnum' を用ã„る。

int dpbnum(DEPOT *depot);
`depot' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®ãƒã‚±ãƒƒãƒˆé…列ã®è¦ç´ æ•°ã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰ -1 ã§ã‚る。

データベースã®ãƒã‚±ãƒƒãƒˆé…列ã®åˆ©ç”¨æ¸ˆã¿ã®è¦ç´ æ•°ã‚’å¾—ã‚‹ã«ã¯ã€é–¢æ•° `dpbusenum' を用ã„る。

int dpbusenum(DEPOT *depot);
`depot' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰ãƒã‚±ãƒƒãƒˆé…列ã®åˆ©ç”¨æ¸ˆã¿ã®è¦ç´ æ•°ã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰ -1 ã§ã‚る。ã“ã®é–¢æ•°ã¯ãƒã‚±ãƒƒãƒˆé…列ã®å…¨ã¦ã®è¦ç´ ã‚’å‚ç…§ã™ã‚‹ã®ã§ã€åŠ¹çŽ‡ãŒæ‚ªã„。

データベースã®ãƒ¬ã‚³ãƒ¼ãƒ‰æ•°ã‚’å¾—ã‚‹ã«ã¯ã€é–¢æ•° `dprnum' を用ã„る。

int dprnum(DEPOT *depot);
`depot' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®ãƒ¬ã‚³ãƒ¼ãƒ‰æ•°ã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰ -1 ã§ã‚る。

データベースãƒãƒ³ãƒ‰ãƒ«ãŒãƒ©ã‚¤ã‚¿ã‹ã©ã†ã‹ã‚’調ã¹ã‚‹ã«ã¯ã€é–¢æ•° `dpwritable' を用ã„る。

int dpwritable(DEPOT *depot);
`depot' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚戻り値ã¯ãƒ©ã‚¤ã‚¿ãªã‚‰çœŸã§ã‚りã€ãã†ã§ãªã‘れã°å½ã§ã‚る。

データベースã«è‡´å‘½çš„エラーãŒèµ·ããŸã‹ã©ã†ã‹ã‚’調ã¹ã‚‹ã«ã¯ã€é–¢æ•° `dpfatalerror' を用ã„る。

int dpfatalerror(DEPOT *depot);
`depot' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚戻り値ã¯è‡´å‘½çš„エラーãŒã‚れã°çœŸã§ã‚りã€ãã†ã§ãªã‘れã°å½ã§ã‚る。

データベースファイルã®inode番å·ã‚’å¾—ã‚‹ã«ã¯ã€é–¢æ•° `dpinode' を用ã„る。

int dpinode(DEPOT *depot);
`depot' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚戻り値ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルã®inode番å·ã§ã‚る。

ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®æœ€çµ‚更新時刻を得るã«ã¯ã€é–¢æ•° `dpmtime' を用ã„る。

time_t dpmtime(DEPOT *depot);
`depot' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚戻り値ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®æœ€çµ‚更新時刻ã§ã‚る。

データベースファイルã®ãƒ•ァイルディスクリプタを得るã«ã¯ã€é–¢æ•° `dpfdesc' を用ã„る。

int dpfdesc(DEPOT *depot);
`depot' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚戻り値ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルã®ãƒ•ァイルディスクリプタã§ã‚る。データベースã®ãƒ•ァイルディスクリプタを直接æ“ã‚‹ã“ã¨ã¯æŽ¨å¥¨ã•れãªã„。

データベースファイルを削除ã™ã‚‹ã«ã¯ã€é–¢æ•° `dpremove' を用ã„る。

int dpremove(const char *name);
`name' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルã®åå‰ã‚’指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰çœŸã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰å½ã§ã‚る。

壊れãŸãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルを修復ã™ã‚‹ã«ã¯ã€é–¢æ•° `dprepair' を用ã„る。

int dprepair(const char *name);
`name' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルã®åå‰ã‚’指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰çœŸã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰å½ã§ã‚る。修復ã•れãŸãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®å…¨ãƒ¬ã‚³ãƒ¼ãƒ‰ãŒå…ƒæ¥ã‚‚ã—ãã¯æœŸå¾…ã•ã‚Œã‚‹çŠ¶æ…‹ã«æˆ»ã‚‹ä¿è¨¼ã¯ãªã„。

å…¨ã¦ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’エンディアンéžä¾å­˜ã®ãƒ‡ãƒ¼ã‚¿ã¨ã—ã¦ãƒ€ãƒ³ãƒ—ã™ã‚‹ã«ã¯ã€é–¢æ•° `dpexportdb' を用ã„る。

int dpexportdb(DEPOT *depot, const char *name);
`depot' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`name' ã¯å‡ºåŠ›ãƒ•ã‚¡ã‚¤ãƒ«ã®åå‰ã‚’指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰çœŸã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰å½ã§ã‚る。

エンディアンéžä¾å­˜ãƒ‡ãƒ¼ã‚¿ã‹ã‚‰å…¨ã¦ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’ロードã™ã‚‹ã«ã¯ã€é–¢æ•° `dpimportdb' を用ã„る。

int dpimportdb(DEPOT *depot, const char *name);
`depot' ã¯ãƒ©ã‚¤ã‚¿ã§æŽ¥ç¶šã—ãŸãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚データベースã¯ç©ºã§ãªã‘れã°ãªã‚‰ãªã„。`name' ã¯å…¥åŠ›ãƒ•ã‚¡ã‚¤ãƒ«ã®åå‰ã‚’指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰çœŸã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰å½ã§ã‚る。

データベースファイルã‹ã‚‰ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’直接å–å¾—ã™ã‚‹ã«ã¯ã€é–¢æ•° `dpsnaffle' を用ã„る。

char *dpsnaffle(const char *name, const char *kbuf, int ksiz, int *sp);
`name' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルã®åå‰ã‚’指定ã™ã‚‹ã€‚`kbuf' ã¯ã‚­ãƒ¼ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`ksiz' ã¯ã‚­ãƒ¼ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã‹ã€è² æ•°ãªã‚‰ `strlen(kbuf)' ã®å€¤ã¨ãªã‚‹ã€‚`start' ã¯å€¤ã®é ˜åŸŸã‹ã‚‰æŠ½å‡ºã™ã‚‹æœ€åˆã®ãƒã‚¤ãƒˆã®ã‚ªãƒ•セットを指定ã™ã‚‹ã€‚`max' ã¯å€¤ã®é ˜åŸŸã‹ã‚‰æŠ½å‡ºã™ã‚‹ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã‹ã€è² æ•°ãªã‚‰ç„¡åˆ¶é™ã¨ãªã‚‹ã€‚`sp' ㌠`NULL' ã§ãªã‘れã°ã€ãã®å‚ç…§å…ˆã«æŠ½å‡ºã—ãŸé ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’æ ¼ç´ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰å€¤ã‚’æ ¼ç´ã—ãŸé ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰ `NULL' ã§ã‚る。該当ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ãŒãªã„å ´åˆã‚‚ `NULL' ã‚’è¿”ã™ã€‚å–り出ãã†ã¨ã—ãŸå€¤ã®ã‚µã‚¤ã‚ºãŒ `start' よりå°ã•ã‹ã£ãŸå ´åˆã«ã¯è©²å½“ã¨ã¿ãªã•ãªã„。戻り値ã®é ˜åŸŸã¯ã€å®Ÿéš›ã«ã¯1ãƒã‚¤ãƒˆå¤šã確ä¿ã—ã¦çµ‚端文字ãŒç½®ã‹ã‚Œã‚‹ã®ã§ã€æ–‡å­—列ã¨ã—ã¦åˆ©ç”¨ã§ãる。戻り値ã®é ˜åŸŸã¯ `malloc' ã§ç¢ºä¿ã•れるã®ã§ã€ä¸è¦ã«ãªã£ãŸã‚‰ `free' ã§è§£æ”¾ã™ã‚‹ã¹ãã§ã‚る。ã“ã®é–¢æ•°ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルãŒåˆ¥ã®ãƒ—ロセスã«ãƒ­ãƒƒã‚¯ã•れã¦ã„ã¦ã‚‚利用ã§ãã‚‹ãŒã€æœ€æ–°ã®æ›´æ–°ãŒå映ã•れã¦ã„ã‚‹ä¿è¨¼ã¯ãªã„。

データベースã®å†…部ã§ç”¨ã„ã‚‹ãƒãƒƒã‚·ãƒ¥é–¢æ•°ã¨ã—ã¦ã€é–¢æ•° `dpinnerhash' ãŒã‚る。

int dpinnerhash(const char *kbuf, int ksiz);
`kbuf' ã¯ã‚­ãƒ¼ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`ksiz' ã¯ã‚­ãƒ¼ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã‹ã€è² æ•°ãªã‚‰ `strlen(kbuf)' ã®å€¤ã¨ãªã‚‹ã€‚戻り値ã¯ã‚­ãƒ¼ã‹ã‚‰31ビット長ã®ãƒãƒƒã‚·ãƒ¥å€¤ã‚’算出ã—ãŸå€¤ã§ã‚る。ã“ã®é–¢æ•°ã¯ã‚¢ãƒ—リケーションãŒãƒã‚±ãƒƒãƒˆé…列ã®çŠ¶æ…‹ã‚’äºˆæ¸¬ã™ã‚‹éš›ã«å½¹ç«‹ã¤ã€‚

データベースã®å†…部ã§ç”¨ã„ã‚‹ãƒãƒƒã‚·ãƒ¥é–¢æ•°ã¨ç‹¬ç«‹ã—ãŸãƒãƒƒã‚·ãƒ¥é–¢æ•°ã¨ã—ã¦ã€é–¢æ•° `dpouterhash' ãŒã‚る。

int dpouterhash(const char *kbuf, int ksiz);
`kbuf' ã¯ã‚­ãƒ¼ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`ksiz' ã¯ã‚­ãƒ¼ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã‹ã€è² æ•°ãªã‚‰ `strlen(kbuf)' ã®å€¤ã¨ãªã‚‹ã€‚戻り値ã¯ã‚­ãƒ¼ã‹ã‚‰31ビット長ã®ãƒãƒƒã‚·ãƒ¥å€¤ã‚’算出ã—ãŸå€¤ã§ã‚る。ã“ã®é–¢æ•°ã¯ã‚¢ãƒ—リケーションãŒãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®æ›´ã«ä¸Šã§ãƒãƒƒã‚·ãƒ¥ã‚¢ãƒ«ã‚´ãƒªã‚ºãƒ ã‚’利用ã™ã‚‹éš›ã«å½¹ç«‹ã¤ã€‚

ã‚る数以上ã®è‡ªç„¶æ•°ã®ç´ æ•°ã‚’å¾—ã‚‹ã«ã¯ã€é–¢æ•° `dpprimenum' を用ã„る。

int dpprimenum(int num);
`num' ã¯é©å½“ãªè‡ªç„¶æ•°ã‚’指定ã™ã‚‹ã€‚戻り値ã¯ã€æŒ‡å®šã—ãŸæ•°ã¨åŒã˜ã‹ã‚ˆã‚Šå¤§ããã‹ã¤ãªã‚‹ã¹ãå°ã•ã„自然数ã®ç´ æ•°ã§ã‚る。ã“ã®é–¢æ•°ã¯ã‚¢ãƒ—リケーションãŒåˆ©ç”¨ã™ã‚‹ãƒã‚±ãƒƒãƒˆé…列ã®ã‚µã‚¤ã‚ºã‚’決ã‚ã‚‹å ´åˆã«å½¹ç«‹ã¤ã€‚

サンプルコード

åå‰ã¨å¯¾å¿œã•ã›ã¦é›»è©±ç•ªå·ã‚’æ ¼ç´ã—ã€ãれを検索ã™ã‚‹ã‚¢ãƒ—リケーションã®ã‚µãƒ³ãƒ—ルコードを以下ã«ç¤ºã™ã€‚

#include <depot.h>
#include <stdlib.h>
#include <stdio.h>

#define NAME     "mikio"
#define NUMBER   "000-1234-5678"
#define DBNAME   "book"

int main(int argc, char **argv){
  DEPOT *depot;
  char *val;

  /* データベースを開ã */
  if(!(depot = dpopen(DBNAME, DP_OWRITER | DP_OCREAT, -1))){
    fprintf(stderr, "dpopen: %s\n", dperrmsg(dpecode));
    return 1;
  }

  /* レコードを格ç´ã™ã‚‹ */
  if(!dpput(depot, NAME, -1, NUMBER, -1, DP_DOVER)){
    fprintf(stderr, "dpput: %s\n", dperrmsg(dpecode));
  }

  /* レコードをå–å¾—ã™ã‚‹ */
  if(!(val = dpget(depot, NAME, -1, 0, -1, NULL))){
    fprintf(stderr, "dpget: %s\n", dperrmsg(dpecode));
  } else {
    printf("Name: %s\n", NAME);
    printf("Number: %s\n", val);
    free(val);
  }

  /* データベースを閉ã˜ã‚‹ */
  if(!dpclose(depot)){
    fprintf(stderr, "dpclose: %s\n", dperrmsg(dpecode));
    return 1;
  }

  return 0;
}

データベースã®å…¨ã¦ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’表示ã™ã‚‹ã‚¢ãƒ—リケーションã®ã‚µãƒ³ãƒ—ルコードを以下ã«ç¤ºã™ã€‚

#include <depot.h>
#include <stdlib.h>
#include <stdio.h>

#define DBNAME   "book"

int main(int argc, char **argv){
  DEPOT *depot;
  char *key, *val;

  /* データベースを開ã */
  if(!(depot = dpopen(DBNAME, DP_OREADER, -1))){
    fprintf(stderr, "dpopen: %s\n", dperrmsg(dpecode));
    return 1;
  }

  /* ã‚¤ãƒ†ãƒ¬ãƒ¼ã‚¿ã‚’åˆæœŸåŒ–ã™ã‚‹ */
  if(!dpiterinit(depot)){
    fprintf(stderr, "dpiterinit: %s\n", dperrmsg(dpecode));
  }

  /* イテレータを走査ã™ã‚‹ */
  while((key = dpiternext(depot, NULL)) != NULL){
    if(!(val = dpget(depot, key, -1, 0, -1, NULL))){
      fprintf(stderr, "dpget: %s\n", dperrmsg(dpecode));
      free(key);
      break;
    }
    printf("%s: %s\n", key, val);
    free(val);
    free(key);
  }

  /* データベースを閉ã˜ã‚‹ */
  if(!dpclose(depot)){
    fprintf(stderr, "dpclose: %s\n", dperrmsg(dpecode));
    return 1;
  }

  return 0;
}

注記

Depotを利用ã—ãŸãƒ—ログラムをビルドã™ã‚‹ã«ã¯ã€ãƒ©ã‚¤ãƒ–ラリ `libqdbm.a' ã¾ãŸã¯ `libqdbm.so' をリンク対象ã«åŠ ãˆã‚‹å¿…è¦ãŒã‚る。例ãˆã°ã€`sample.c' ã‹ã‚‰ `sample' を作るã«ã¯ã€ä»¥ä¸‹ã®ã‚ˆã†ã«ãƒ“ルドを行ã†ã€‚

gcc -I/usr/local/include -o sample sample.c -L/usr/local/lib -lqdbm

POSIXスレッドを有効ã«ã—ã¦QDBMをビルドã—ãŸå ´åˆã€å¤–部変数 `dpecode' ã¯ã‚¹ãƒ¬ãƒƒãƒ‰å›ºæœ‰ãƒ‡ãƒ¼ã‚¿ã¸ã®å‚ç…§ã¨ã—ã¦æ‰±ã‚れã€Depotã®å„関数ã¯ãƒªã‚¨ãƒ³ãƒˆãƒ©ãƒ³ãƒˆã«ãªã‚‹ã€‚ãã®å ´åˆã€ã‚¹ãƒ¬ãƒƒãƒ‰é–“ã§åŒæ™‚ã«åŒã˜ãƒãƒ³ãƒ‰ãƒ«ã«ã‚¢ã‚¯ã‚»ã‚¹ã—ãªã„é™ã‚Šã¯ã€å„関数ã¯ã‚¹ãƒ¬ãƒƒãƒ‰ã‚»ãƒ¼ãƒ•ã§ã‚る。ãŸã ã—ã€`errno' ã‚„ `malloc' ç­‰ãŒã‚¹ãƒ¬ãƒƒãƒ‰ã‚»ãƒ¼ãƒ•ãªå‡¦ç†ç³»ã§ã‚ã‚‹ã“ã¨ãŒå‰æã¨ãªã‚‹ã€‚


Depot用コマンド

Depotã«å¯¾å¿œã™ã‚‹ã‚³ãƒžãƒ³ãƒ‰ãƒ©ã‚¤ãƒ³ã‚¤ãƒ³ã‚¿ãƒ•ェースã¯ä»¥ä¸‹ã®ã‚‚ã®ã§ã‚る。

コマンド `dpmgr' ã¯Depotã‚„ãã®ã‚¢ãƒ—リケーションã®ãƒ‡ãƒãƒƒã‚°ã«å½¹ç«‹ã¤ãƒ„ールã§ã‚る。データベースを更新ã—ãŸã‚Šã€ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®çŠ¶æ…‹ã‚’èª¿ã¹ãŸã‚Šã™ã‚‹æ©Ÿèƒ½ã‚’æŒã¤ã€‚シェルスクリプトã§ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚¢ãƒ—リケーションを作るã®ã«ã‚‚利用ã§ãã‚‹ã€‚ä»¥ä¸‹ã®æ›¸å¼ã§ç”¨ã„る。`name' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹åã€`key' ã¯ãƒ¬ã‚³ãƒ¼ãƒ‰ã®ã‚­ãƒ¼ã€`val' ã¯ãƒ¬ã‚³ãƒ¼ãƒ‰ã®å€¤ã‚’指定ã™ã‚‹ã€‚

dpmgr create [-s] [-bnum num] name
データベースファイルを作æˆã™ã‚‹ã€‚
dpmgr put [-kx|-ki] [-vx|-vi|-vf] [-keep|-cat] [-na] name key val
キーã¨å€¤ã«å¯¾å¿œã™ã‚‹ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’追加ã™ã‚‹ã€‚
dpmgr out [-kx|-ki] name key
キーã«å¯¾å¿œã™ã‚‹ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’削除ã™ã‚‹ã€‚
dpmgr get [-nl] [-kx|-ki] [-start num] [-max num] [-ox] [-n] name key
キーã«å¯¾å¿œã™ã‚‹ãƒ¬ã‚³ãƒ¼ãƒ‰ã®å€¤ã‚’å–å¾—ã—ã¦æ¨™æº–出力ã™ã‚‹ã€‚
dpmgr list [-nl] [-k|-v] [-ox] name
データベース内ã®å…¨ã¦ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã®ã‚­ãƒ¼ã¨å€¤ã‚’ã‚¿ãƒ–ã¨æ”¹è¡Œã§åŒºåˆ‡ã£ã¦æ¨™æº–出力ã™ã‚‹ã€‚
dpmgr optimize [-bnum num] [-na] name
データベースを最é©åŒ–ã™ã‚‹ã€‚
dpmgr inform [-nl] name
データベースã®é›‘å¤šãªæƒ…報を出力ã™ã‚‹ã€‚
dpmgr remove name
データベースファイルを削除ã™ã‚‹ã€‚
dpmgr repair name
壊れãŸãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルを修復ã™ã‚‹ã€‚
dpmgr exportdb name file
å…¨ã¦ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’エンディアンéžä¾å­˜ã®ãƒ‡ãƒ¼ã‚¿ã¨ã—ã¦ãƒ€ãƒ³ãƒ—ã™ã‚‹ã€‚
dpmgr importdb [-bnum num] name file
エンディアンéžä¾å­˜ãƒ‡ãƒ¼ã‚¿ã‹ã‚‰å…¨ã¦ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’ロードã™ã‚‹ã€‚
dpmgr snaffle [-kx|-ki] [-ox] [-n] name key
ロックã•れãŸãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‹ã‚‰ã‚­ãƒ¼ã«å¯¾å¿œã™ã‚‹ãƒ¬ã‚³ãƒ¼ãƒ‰ã®å€¤ã‚’å–å¾—ã—ã¦æ¨™æº–出力ã™ã‚‹ã€‚
dpmgr version
QDBMã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³æƒ…報を標準出力ã™ã‚‹ã€‚

å„オプションã¯ä»¥ä¸‹ã®æ©Ÿèƒ½ã‚’æŒã¤ã€‚

  • -s : ファイルをスパースã«ã™ã‚‹ã€‚
  • -bnum num : ãƒã‚±ãƒƒãƒˆé…列ã®è¦ç´ æ•°ã‚’ `num' ã«æŒ‡å®šã™ã‚‹ã€‚
  • -kx : 2æ¡å˜ä½ã®16進数ã«ã‚ˆã‚‹ãƒã‚¤ãƒŠãƒªè¡¨ç¾ã¨ã—㦠`key' を扱ã†ã€‚
  • -ki : 10進数ã«ã‚ˆã‚‹æ•°å€¤è¡¨ç¾ã¨ã—㦠`key' を扱ã†ã€‚
  • -vx : 2æ¡å˜ä½ã®16進数ã«ã‚ˆã‚‹ãƒã‚¤ãƒŠãƒªè¡¨ç¾ã¨ã—㦠`val' を扱ã†ã€‚
  • -vi : 10進数ã«ã‚ˆã‚‹æ•°å€¤è¡¨ç¾ã¨ã—㦠`val' を扱ã†ã€‚
  • -vf : åå‰ãŒ `val' ã®ãƒ•ァイルã®ãƒ‡ãƒ¼ã‚¿ã‚’値ã¨ã—ã¦èª­ã¿è¾¼ã‚€ã€‚
  • -keep : 既存ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã¨ã‚­ãƒ¼ãŒé‡è¤‡æ™‚ã«ä¸Šæ›¸ãã›ãšã«ã‚¨ãƒ©ãƒ¼ã«ã™ã‚‹ã€‚
  • -cat : 既存ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã¨ã‚­ãƒ¼ãŒé‡è¤‡æ™‚ã«å€¤ã‚’末尾ã«è¿½åŠ ã™ã‚‹ã€‚
  • -na : アラインメントを設定ã—ãªã„。
  • -nl : ファイルロックをã‹ã‘ãšã«ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’é–‹ã。
  • -start : 値ã‹ã‚‰å–り出ã™ãƒ‡ãƒ¼ã‚¿ã®é–‹å§‹ã‚ªãƒ•セットを指定ã™ã‚‹ã€‚
  • -max : 値ã‹ã‚‰å–り出ã™ãƒ‡ãƒ¼ã‚¿ã®æœ€å¤§ã®é•·ã•を指定ã™ã‚‹ã€‚
  • -ox : 2æ¡å˜ä½ã®16進数ã«ã‚ˆã‚‹ãƒã‚¤ãƒŠãƒªè¡¨ç¾ã¨ã—ã¦æ¨™æº–出力を行ã†ã€‚
  • -n : æ¨™æº–å‡ºåŠ›ã®æœ«å°¾ã«ä»˜åŠ ã•れる改行文字ã®å‡ºåŠ›ã‚’æŠ‘åˆ¶ã™ã‚‹ã€‚
  • -k : キーã®ã¿ã‚’出力ã™ã‚‹ã€‚
  • -v : 値ã®ã¿ã‚’出力ã™ã‚‹ã€‚

ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯å‡¦ç†ãŒæ­£å¸¸ã«çµ‚了ã™ã‚Œã° 0 ã‚’è¿”ã—ã€ã‚¨ãƒ©ãƒ¼ãŒã‚れã°ãれ以外ã®å€¤ã‚’è¿”ã—ã¦çµ‚了ã™ã‚‹ã€‚環境変数 `QDBMDBGFD' ã®å€¤ã¨ã—ã¦ã€å¤‰æ•° `dpecode' ã®å¤‰æ›´å±¥æ­´ã‚’出力ã™ã‚‹ãƒ•ァイルディスクリプタを指定ã“ã¨ãŒã§ãる。

コマンド `dptest' ã¯Depotã®æ©Ÿèƒ½ãƒ†ã‚¹ãƒˆã‚„性能テストã«ç”¨ã„るツールã§ã‚る。ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã«ã‚ˆã£ã¦ç”Ÿæˆã•れãŸãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルを `dpmgr' ã«ã‚ˆã£ã¦è§£æžã—ãŸã‚Šã€`time' コマンドã«ã‚ˆã£ã¦ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã®å®Ÿè¡Œæ™‚間を計ã£ãŸã‚Šã™ã‚‹ã¨ã‚ˆã„ã€‚ä»¥ä¸‹ã®æ›¸å¼ã§ç”¨ã„る。`name' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹åã€`rnum' ã¯ãƒ¬ã‚³ãƒ¼ãƒ‰æ•°ã€`bnum' ã¯ãƒã‚±ãƒƒãƒˆé…列ã®è¦ç´ æ•°ã€`pnum' ã¯ã‚­ãƒ¼ã®ãƒ‘ターン数ã€`align' ã¯ã‚¢ãƒ©ã‚¤ãƒ³ãƒ¡ãƒ³ãƒˆã®åŸºæœ¬ã‚µã‚¤ã‚ºã€`fbpsiz' ã¯ãƒ•リーブロックプールã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã€‚

dptest write [-s] name rnum bnum
`00000001'ã€`00000002' ã®ã‚ˆã†ã«å¤‰åŒ–ã™ã‚‹8ãƒã‚¤ãƒˆã®ã‚­ãƒ¼ã¨é©å½“ãª8ãƒã‚¤ãƒˆã®å€¤ã‚’連続ã—ã¦ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«è¿½åŠ ã™ã‚‹ã€‚
dptest read [-wb] name
上記ã§ç”Ÿæˆã—ãŸãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®å…¨ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’検索ã™ã‚‹ã€‚
dptest rcat [-c] name rnum bnum pnum align fbpsiz
キーãŒã‚る程度é‡è¤‡ã™ã‚‹ã‚ˆã†ã«ãƒ¬ã‚³ãƒ¼ãƒ‰ã®è¿½åŠ ã‚’è¡Œã„ã€é€£çµãƒ¢ãƒ¼ãƒ‰ã§å‡¦ç†ã™ã‚‹ã€‚
dptest combo name
å„種æ“作ã®çµ„ã¿åˆã‚ã›ãƒ†ã‚¹ãƒˆã‚’行ã†ã€‚
dptest wicked [-c] name rnum
å„種更新æ“作を無作為ã«é¸æŠžã—ã¦å®Ÿè¡Œã™ã‚‹ã€‚

å„オプションã¯ä»¥ä¸‹ã®æ©Ÿèƒ½ã‚’æŒã¤ã€‚

  • -s : ファイルをスパースã«ã™ã‚‹ã€‚
  • -wb : 関数 `dpget' ã®ä»£ã‚りã«é–¢æ•° `dpgetwb' を用ã„る。
  • -c : Cabinã®ãƒžãƒƒãƒ—を使ã£ã¦æ¯”較テストを行ã†ã€‚

ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯å‡¦ç†ãŒæ­£å¸¸ã«çµ‚了ã™ã‚Œã° 0 ã‚’è¿”ã—ã€ã‚¨ãƒ©ãƒ¼ãŒã‚れã°ãれ以外ã®å€¤ã‚’è¿”ã—ã¦çµ‚了ã™ã‚‹ã€‚環境変数 `QDBMDBGFD' ã®å€¤ã¨ã—ã¦ã€å¤‰æ•° `dpecode' ã®å¤‰æ›´å±¥æ­´ã‚’出力ã™ã‚‹ãƒ•ァイルディスクリプタを指定ã“ã¨ãŒã§ãる。

コマンド `dptsv' ã¯ã‚¿ãƒ–区切りã§ã‚­ãƒ¼ã¨å€¤ã‚’表ç¾ã—ãŸè¡Œã‹ã‚‰ãªã‚‹TSVファイルã¨Depotã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’相互変æ›ã™ã‚‹ã€‚ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€QDBMã®ä»–ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã‚„ä»–ã®DBMã¨ã®é–“ã§ãƒ‡ãƒ¼ã‚¿ã®äº¤æ›ã‚’行ã†éš›ã«å½¹ç«‹ã¤ã€‚ã¾ãŸã€ãƒã‚¤ãƒˆã‚ªãƒ¼ãƒ€ã®é•ã†ã‚·ã‚¹ãƒ†ãƒ ã®é–“ã§ãƒ‡ãƒ¼ã‚¿ã‚’交æ›ã™ã‚‹éš›ã«ã‚‚役立ã¤ã€‚ä»¥ä¸‹ã®æ›¸å¼ã§ç”¨ã„る。`name' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹åを指定ã™ã‚‹ã€‚`export' サブコマンドã§ã¯TSVã®ãƒ‡ãƒ¼ã‚¿ã¯æ¨™æº–入力ã‹ã‚‰èª­ã¿è¾¼ã‚€ã€‚キーãŒé‡è¤‡ã™ã‚‹ãƒ¬ã‚³ãƒ¼ãƒ‰ã¯å¾Œè€…を優先ã™ã‚‹ã€‚`-bnum' オプションã®å¼•æ•° `num' ã¯ãƒã‚±ãƒƒãƒˆé…列ã®è¦ç´ æ•°ã‚’指定ã™ã‚‹ã€‚`import' サブコマンドã§ã¯TSVã®ãƒ‡ãƒ¼ã‚¿ãŒæ¨™æº–å‡ºåŠ›ã«æ›¸ã出ã•れる。

dptsv import [-bnum num] [-bin] name
TSVファイルを読ã¿è¾¼ã‚“ã§ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’作æˆã™ã‚‹ã€‚
dptsv export [-bin] name
データベースã®å…¨ã¦ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’TSVファイルã¨ã—ã¦å‡ºåŠ›ã™ã‚‹ã€‚

å„オプションã¯ä»¥ä¸‹ã®æ©Ÿèƒ½ã‚’æŒã¤ã€‚

  • -bnum num : ãƒã‚±ãƒƒãƒˆé…列ã®è¦ç´ æ•°ã‚’ `num' ã«æŒ‡å®šã™ã‚‹ã€‚
  • -bin : Base64å½¢å¼ã§ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’扱ã†ã€‚

ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯å‡¦ç†ãŒæ­£å¸¸ã«çµ‚了ã™ã‚Œã° 0 ã‚’è¿”ã—ã€ã‚¨ãƒ©ãƒ¼ãŒã‚れã°ãれ以外ã®å€¤ã‚’è¿”ã—ã¦çµ‚了ã™ã‚‹ã€‚

Depotã®ã‚³ãƒžãƒ³ãƒ‰ç¾¤ã‚’駆使ã™ã‚‹ã¨ã€ç°¡å˜ãªãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚·ã‚¹ãƒ†ãƒ ãŒæ§‹ç¯‰ã§ãる。例ãˆã° `/etc/password' をユーザåã§æ¤œç´¢ã™ã‚‹ãŸã‚ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’作æˆã™ã‚‹ã«ã¯ã€ä»¥ä¸‹ã®ã‚ˆã†ã«ã™ã‚‹ã€‚

cat /etc/passwd | tr ':' '\t' | dptsv import casket

ãã—ã¦ã€`mikio' ã¨ã„ã†ãƒ¦ãƒ¼ã‚¶ã®æƒ…報をå–り出ã™ã«ã¯ã€ä»¥ä¸‹ã®ã‚ˆã†ã«ã™ã‚‹ã€‚

dpmgr get casket mikio

ã“れらã®ã‚³ãƒžãƒ³ãƒ‰ã¨åŒç­‰ã®æ©Ÿèƒ½ã‚’Depotã®APIを用ã„ã¦å®Ÿè£…ã™ã‚‹ã“ã¨ã‚‚容易ã§ã‚る。


Curia: æ‹¡å¼µAPI

概è¦

Curiaã¯QDBMã®æ‹¡å¼µAPIã§ã‚りã€è¤‡æ•°ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルをディレクトリã§ä¸€æ‹¬ã—ã¦æ‰±ã†æ©Ÿèƒ½ã‚’æä¾›ã™ã‚‹ã€‚データベースを複数ã®ãƒ•ァイルã«åˆ†å‰²ã™ã‚‹ã“ã¨ã§ã€ãƒ•ァイルシステムã«ã‚ˆã‚‹ãƒ•ァイルサイズã®åˆ¶é™ã‚’回é¿ã™ã‚‹ã“ã¨ãŒã§ãる。複数ã®ãƒ‡ãƒã‚¤ã‚¹ã«ãƒ•ァイルを分散ã•ã›ã‚Œã°ã€ã‚¹ã‚±ãƒ¼ãƒ©ãƒ“リティをå‘上ã•ã›ã‚‹ã“ã¨ãŒã§ãる。

Depotã§ã¯ãƒ•ァイルåを指定ã—ã¦ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’構築ã™ã‚‹ãŒã€Curiaã§ã¯ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªåを指定ã—ã¦ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’構築ã™ã‚‹ã€‚指定ã—ãŸãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã®ç›´ä¸‹ã«ã¯ã€`depot' ã¨ã„ã†åå‰ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルãŒç”Ÿæˆã•れる。ã“れã¯ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã®å±žæ€§ã‚’ä¿æŒã™ã‚‹ã‚‚ã®ã§ã‚りã€ãƒ¬ã‚³ãƒ¼ãƒ‰ã®å®Ÿãƒ‡ãƒ¼ã‚¿ã¯æ ¼ç´ã•れãªã„。ãれã¨ã¯åˆ¥ã«ã€ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’分割ã—ãŸå€‹æ•°ã ã‘ã€4æ¡ã®10進数値ã®åå‰ã‚’æŒã¤ã‚µãƒ–ディレクトリãŒç”Ÿæˆã•れã€å„々ã®ã‚µãƒ–ディレクトリã®ä¸­ã«ã¯ `depot' ã¨ã„ã†åå‰ã§ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルãŒç”Ÿæˆã•れる。レコードã®å®Ÿãƒ‡ãƒ¼ã‚¿ã¯ãã‚Œã‚‰ã«æ ¼ç´ã•れる。例ãˆã°ã€`casket' ã¨ã„ã†åå‰ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’作æˆã—ã€åˆ†å‰²æ•°ã‚’3ã«ã™ã‚‹å ´åˆã€`casket/depot'ã€`casket/0001/depot'ã€`casket/0002/depot'ã€`casket/0003/depot' ãŒç”Ÿæˆã•れる。データベースを作æˆã™ã‚‹éš›ã«ã™ã§ã«ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªãŒå­˜åœ¨ã—ã¦ã„ã¦ã‚‚エラーã¨ã¯ãªã‚‰ãªã„。ã—ãŸãŒã£ã¦ã€äºˆã‚サブディレクトリを生æˆã—ã¦ãŠã„ã¦ã€å„々ã«ç•°ãªã‚‹ãƒ‡ãƒã‚¤ã‚¹ã®ãƒ•ァイルシステムをマウントã—ã¦ãŠã‘ã°ã€ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルを複数ã®ãƒ‡ãƒã‚¤ã‚¹ã«åˆ†æ•£ã•ã›ã‚‹ã“ã¨ãŒã§ãる。

Curiaã«ã¯ãƒ©ãƒ¼ã‚¸ã‚ªãƒ–ã‚¸ã‚§ã‚¯ãƒˆã‚’æ‰±ã†æ©Ÿèƒ½ãŒã‚る。通常ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã®ãƒ‡ãƒ¼ã‚¿ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ã‚¡ã‚¤ãƒ«ã«æ ¼ç´ã•れるãŒã€ãƒ©ãƒ¼ã‚¸ã‚ªãƒ–ジェクトã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã®ãƒ‡ãƒ¼ã‚¿ã¯å€‹åˆ¥ã®ãƒ•ã‚¡ã‚¤ãƒ«ã«æ ¼ç´ã•れる。ラージオブジェクトã®ãƒ•ァイルã¯ãƒãƒƒã‚·ãƒ¥å€¤ã‚’å…ƒã«ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã«åˆ†ã‘ã¦æ ¼ç´ã•れるã®ã§ã€é€šå¸¸ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã«ã¯åŠ£ã‚‹ãŒã€ãれãªã‚Šã®é€Ÿåº¦ã§å‚ç…§ã§ãる。サイズãŒå¤§ããå‚照頻度ãŒä½Žã„データã¯ã€ãƒ©ãƒ¼ã‚¸ã‚ªãƒ–ジェクトã¨ã—ã¦ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルã‹ã‚‰åˆ†é›¢ã™ã¹ãã§ã‚る。ãã†ã™ã‚Œã°ã€é€šå¸¸ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã«å¯¾ã™ã‚‹å‡¦ç†é€Ÿåº¦ãŒå‘上ã™ã‚‹ã€‚ラージオブジェクトã®ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªéšŽå±¤ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ã‚¡ã‚¤ãƒ«ãŒæ ¼ç´ã•れるサブディレクトリã®ä¸­ã® `lob' ã¨ã„ã†åå‰ã®ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã®ä¸­ã«ä½œã‚‰ã‚Œã‚‹ã€‚通常ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã¨ãƒ©ãƒ¼ã‚¸ã‚ªãƒ–ジェクトã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã¯ã‚­ãƒ¼ç©ºé–“ãŒç•°ãªã‚Šã€äº’ã„ã«å¹²æ¸‰ã™ã‚‹ã“ã¨ã¯ãªã„。

Curiaを使ã†ãŸã‚ã«ã¯ã€`depot.h' 㨠`curia.h' 㨠`stdlib.h' をインクルードã™ã¹ãã§ã‚る。通常ã€ã‚½ãƒ¼ã‚¹ãƒ•ァイルã®å†’頭付近ã§ä»¥ä¸‹ã®è¨˜è¿°ã‚’行ã†ã€‚

#include <depot.h>
#include <curia.h>
#include <stdlib.h>

Curiaã§ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’扱ã†éš›ã«ã¯ã€`CURIA' åž‹ã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’ãƒãƒ³ãƒ‰ãƒ«ã¨ã—ã¦ç”¨ã„る。ã“れã¯ã€`stdio.h' ã®å„種ルーãƒãƒ³ãŒãƒ•ァイル入出力㫠`FILE' åž‹ã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’用ã„ã‚‹ã®ã«ä¼¼ã¦ã„る。ãƒãƒ³ãƒ‰ãƒ«ã¯ã€é–¢æ•° `cropen' ã§é–‹ãã€é–¢æ•° `crclose' ã§é–‰ã˜ã‚‹ã€‚ãƒãƒ³ãƒ‰ãƒ«ã®ãƒ¡ãƒ³ãƒã‚’直接å‚ç…§ã™ã‚‹ã“ã¨ã¯æŽ¨å¥¨ã•れãªã„。データベースã«è‡´å‘½çš„ãªã‚¨ãƒ©ãƒ¼ãŒèµ·ããŸå ´åˆã¯ã€ä»¥å¾Œãã®ãƒãƒ³ãƒ‰ãƒ«ã«å¯¾ã™ã‚‹ `crclose' を除ãå…¨ã¦ã®æ“作ã¯ä½•ã‚‚ã›ãšã«ã‚¨ãƒ©ãƒ¼ã‚’è¿”ã™ã€‚ã²ã¨ã¤ã®ãƒ—ロセスã§è¤‡æ•°ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã‚’åŒæ™‚ã«åˆ©ç”¨ã™ã‚‹ã“ã¨ã¯å¯èƒ½ã§ã‚ã‚‹ãŒã€åŒã˜ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã®è¤‡æ•°ã®ãƒãƒ³ãƒ‰ãƒ«ã‚’利用ã—ã¦ã¯ãªã‚‰ãªã„。

Curiaã§ã‚‚Depotã¨åŒã˜ã外部変数 `dpecode' ã«ç›´å‰ã®ã‚¨ãƒ©ãƒ¼ã‚³ãƒ¼ãƒ‰ãŒè¨˜éŒ²ã•れる。エラーコードã«å¯¾å¿œã™ã‚‹ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸æ–‡å­—列を得るã«ã¯ã€é–¢æ•° `dperrmsg' を用ã„る。

API

データベースã®ãƒãƒ³ãƒ‰ãƒ«ã‚’作æˆã™ã‚‹ã«ã¯ã€é–¢æ•° `cropen' を用ã„る。

CURIA *cropen(const char *name, int omode, int bnum, int dnum);
`name' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã®åå‰ã‚’指定ã™ã‚‹ã€‚`omode' ã¯æŽ¥ç¶šãƒ¢ãƒ¼ãƒ‰ã‚’æŒ‡å®šã—ã€`CR_OREADER' ãªã‚‰ãƒªãƒ¼ãƒ€ã€`CR_OWRITER' ãªã‚‰ãƒ©ã‚¤ã‚¿ã¨ãªã‚‹ã€‚`CR_OWRITER' ã®å ´åˆã€`CR_OCREAT' ã¾ãŸã¯ `CR_OTRUNC' ã¨ã®ãƒ“ット論ç†å’Œã«ã™ã‚‹ã“ã¨ãŒã§ãる。`CR_OCREAT' ã¯ãƒ•ァイルãŒç„¡ã„å ´åˆã«æ–°è¦ä½œæˆã™ã‚‹ã“ã¨ã‚’指示ã—ã€`CR_OTRUNC' ã¯ãƒ•ァイルãŒå­˜åœ¨ã—ã¦ã‚‚作り直ã™ã“ã¨ã‚’指示ã™ã‚‹ã€‚`CR_OREADER' 㨠`CR_OWRITER' ã®ä¸¡æ–¹ã§ `CR_ONOLCK' ã¾ãŸã¯ `CR_OLCKNB' ã¨ã®ãƒ“ット論ç†å’Œã«ã™ã‚‹ã“ã¨ãŒã§ãã‚‹ãŒã€å‰è€…ã¯ãƒ•ァイルロックをã‹ã‘ãšã«ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’é–‹ãã“ã¨ã‚’指示ã—ã€å¾Œè€…ã¯ãƒ–ロックã›ãšã«ãƒ­ãƒƒã‚¯ã‚’ã‹ã‘ã‚‹ã“ã¨ã‚’指示ã™ã‚‹ã€‚`CR_OCREAT' 㯠`CR_OSPARSE' ã¨ã®ãƒ“ット論ç†å’Œã«ã™ã‚‹ã“ã¨ãŒã§ãã‚‹ãŒã€ãれã¯ç”Ÿæˆã•れるファイルをスパースã«ã™ã‚‹ã“ã¨ã‚’指示ã™ã‚‹ã€‚`bnum' ã¯ãƒã‚±ãƒƒãƒˆé…列ã®è¦ç´ æ•°ã®ç›®å®‰ã‚’指定ã™ã‚‹ãŒã€0 以下ãªã‚‰ãƒ‡ãƒ•ォルト値ãŒä½¿ã‚れる。ãƒã‚±ãƒƒãƒˆé…列ã®è¦ç´ æ•°ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’作æˆã™ã‚‹æ™‚ã«æ±ºã‚ã‚‰ã‚Œã€æœ€é©åŒ–ä»¥å¤–ã®æ‰‹æ®µã§å¤‰æ›´ã™ã‚‹ã“ã¨ã¯ã§ããªã„。ãƒã‚±ãƒƒãƒˆé…列ã®è¦ç´ æ•°ã¯ã€æ ¼ç´ã™ã‚‹ãƒ¬ã‚³ãƒ¼ãƒ‰æ•°ã®åŠåˆ†ã‹ã‚‰4å€ç¨‹åº¦ã«ã™ã‚‹ã®ãŒã‚ˆã„。`dnum' ã¯è¦ç´ ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®æ•°ã‚’指定ã™ã‚‹ãŒã€0 以下ãªã‚‰ãƒ‡ãƒ•ォルト値ãŒä½¿ã‚れる。データベースファイルã®åˆ†å‰²æ•°ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’作æˆã™ã‚‹æ™‚ã«æŒ‡å®šã—ãŸã‚‚ã®ã‹ã‚‰å¤‰æ›´ã™ã‚‹ã“ã¨ã¯ã§ããªã„。データベースファイルã®åˆ†å‰²æ•°ã®æœ€å¤§å€¤ã¯ 512 個ã§ã‚る。戻り値ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã§ã‚ã‚‹ã‹ã€ã‚¨ãƒ©ãƒ¼ãªã‚‰ `NULL' ã§ã‚ã‚‹ã€‚ãƒ©ã‚¤ã‚¿ï¼ˆèª­ã¿æ›¸ã両用モード)ã§ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルを開ãéš›ã«ã¯ãã®ãƒ•ァイルã«å¯¾ã—ã¦æŽ’ä»–ãƒ­ãƒƒã‚¯ãŒã‹ã‘られã€ãƒªãƒ¼ãƒ€ï¼ˆèª­ã¿è¾¼ã¿å°‚用モード)ã§é–‹ãéš›ã«ã¯å…±æœ‰ãƒ­ãƒƒã‚¯ãŒã‹ã‘られる。ãã®éš›ã«ã¯è©²å½“ã®ãƒ­ãƒƒã‚¯ãŒã‹ã‘られるã¾ã§åˆ¶å¾¡ãŒãƒ–ロックã™ã‚‹ã€‚`CR_ONOLCK' を使ã†å ´åˆã€ã‚¢ãƒ—ãƒªã‚±ãƒ¼ã‚·ãƒ§ãƒ³ãŒæŽ’ä»–åˆ¶å¾¡ã®è²¬ä»»ã‚’è² ã†ã€‚

データベースã¨ã®æŽ¥ç¶šã‚’é–‰ã˜ã¦ãƒãƒ³ãƒ‰ãƒ«ã‚’破棄ã™ã‚‹ã«ã¯ã€é–¢æ•° `crclose' を用ã„る。

int crclose(CURIA *curia);
`curia' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰çœŸã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰å½ã§ã‚ã‚‹ã€‚ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®æ›´æ–°å†…容ã¯ã€æŽ¥ç¶šã‚’é–‰ã˜ãŸæ™‚点ã§åˆã‚ã¦ãƒ•ァイルã¨åŒæœŸã•れる。ライタã§ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’é–‹ã„ãŸå ´åˆã€é©åˆ‡ã«æŽ¥ç¶šã‚’é–‰ã˜ãªã„ã¨ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãŒç ´å£Šã•れる。閉ã˜ãŸãƒãƒ³ãƒ‰ãƒ«ã®é ˜åŸŸã¯è§£æ”¾ã•れるã®ã§ã€ä»¥å¾Œã¯åˆ©ç”¨ã§ããªããªã‚‹ã€‚

レコードを追加ã™ã‚‹ã«ã¯ã€é–¢æ•° `crput' を用ã„る。

int crput(CURIA *curia, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int dmode);
`curia' ã¯ãƒ©ã‚¤ã‚¿ã§æŽ¥ç¶šã—ãŸãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`kbuf' ã¯ã‚­ãƒ¼ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`ksiz' ã¯ã‚­ãƒ¼ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã‹ã€è² æ•°ãªã‚‰ `strlen(kbuf)' ã®å€¤ã¨ãªã‚‹ã€‚`vbuf' ã¯å€¤ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`vsiz' ã¯å€¤ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã‹ã€è² æ•°ãªã‚‰ `strlen(vbuf)' ã®å€¤ã¨ãªã‚‹ã€‚`dmode' ã¯ã‚­ãƒ¼ãŒæ—¢å­˜ãƒ¬ã‚³ãƒ¼ãƒ‰ã¨é‡è¤‡ã—ãŸéš›ã®åˆ¶å¾¡ã‚’指定ã™ã‚‹ã€‚`CR_DOVER' ã¯æ—¢å­˜ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã®å€¤ã‚’上書ãã—ã€`CR_DKEEP' ã¯æ—¢å­˜ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’残ã—ã¦ã‚¨ãƒ©ãƒ¼ã‚’è¿”ã—ã€`DP_DCAT' ã¯æŒ‡å®šã•れãŸå€¤ã‚’既存ã®å€¤ã®æœ«å°¾ã«åŠ ãˆã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰çœŸã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰å½ã§ã‚る。

レコードを削除ã™ã‚‹ã«ã¯ã€é–¢æ•° `crout' を用ã„る。

int crout(CURIA *curia, const char *kbuf, int ksiz);
`curia' ã¯ãƒ©ã‚¤ã‚¿ã§æŽ¥ç¶šã—ãŸãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`kbuf' ã¯ã‚­ãƒ¼ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`ksiz' ã¯ã‚­ãƒ¼ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã‹ã€è² æ•°ãªã‚‰ `strlen(kbuf)' ã®å€¤ã¨ãªã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰çœŸã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰å½ã§ã‚る。該当ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ãŒãªã„å ´åˆã‚‚å½ã‚’è¿”ã™ã€‚

レコードをå–å¾—ã™ã‚‹ã«ã¯ã€é–¢æ•° `crget' を用ã„る。

char *crget(CURIA *curia, const char *kbuf, int ksiz, int start, int max, int *sp);
`curia' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`kbuf' ã¯ã‚­ãƒ¼ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`ksiz' ã¯ã‚­ãƒ¼ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã‹ã€è² æ•°ãªã‚‰ `strlen(kbuf)' ã®å€¤ã¨ãªã‚‹ã€‚`start' ã¯å€¤ã®é ˜åŸŸã‹ã‚‰æŠ½å‡ºã™ã‚‹æœ€åˆã®ãƒã‚¤ãƒˆã®ã‚ªãƒ•セットを指定ã™ã‚‹ã€‚`max' ã¯å€¤ã®é ˜åŸŸã‹ã‚‰æŠ½å‡ºã™ã‚‹ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã‹ã€è² æ•°ãªã‚‰ç„¡åˆ¶é™ã¨ãªã‚‹ã€‚`sp' ㌠`NULL' ã§ãªã‘れã°ã€ãã®å‚ç…§å…ˆã«æŠ½å‡ºã—ãŸé ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’æ ¼ç´ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰å€¤ã‚’æ ¼ç´ã—ãŸé ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰ `NULL' ã§ã‚る。該当ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ãŒãªã„å ´åˆã‚‚ `NULL' ã‚’è¿”ã™ã€‚å–り出ãã†ã¨ã—ãŸå€¤ã®ã‚µã‚¤ã‚ºãŒ `start' よりå°ã•ã‹ã£ãŸå ´åˆã«ã¯è©²å½“ã¨ã¿ãªã•ãªã„。戻り値ã®é ˜åŸŸã¯ã€å®Ÿéš›ã«ã¯1ãƒã‚¤ãƒˆå¤šã確ä¿ã—ã¦çµ‚端文字ãŒç½®ã‹ã‚Œã‚‹ã®ã§ã€æ–‡å­—列ã¨ã—ã¦åˆ©ç”¨ã§ãる。戻り値ã®é ˜åŸŸã¯ `malloc' ã§ç¢ºä¿ã•れるã®ã§ã€ä¸è¦ã«ãªã£ãŸã‚‰ `free' ã§è§£æ”¾ã™ã‚‹ã¹ãã§ã‚る。

レコードをå–å¾—ã—ã¦ãƒãƒƒãƒ•ã‚¡ã«æ›¸ã込むã«ã¯ã€é–¢æ•° `crgetwb' を用ã„る。

int crgetwb(CURIA *curia, const char *kbuf, int ksiz, int start, int max, char *vbuf);
`curia' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`kbuf' ã¯ã‚­ãƒ¼ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`ksiz' ã¯ã‚­ãƒ¼ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã‹ã€è² æ•°ãªã‚‰ `strlen(kbuf)' ã®å€¤ã¨ãªã‚‹ã€‚`start' ã¯å€¤ã®é ˜åŸŸã‹ã‚‰æŠ½å‡ºã™ã‚‹æœ€åˆã®ãƒã‚¤ãƒˆã®ã‚ªãƒ•セットを指定ã™ã‚‹ã€‚`max' ã¯å€¤ã®é ˜åŸŸã‹ã‚‰æŠ½å‡ºã™ã‚‹ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã€‚ãã‚Œã¯æ›¸ãè¾¼ã¿ç”¨ã®ãƒãƒƒãƒ•ã‚¡ã®ã‚µã‚¤ã‚ºä»¥ä¸‹ã§ã‚ã‚‹å¿…è¦ãŒã‚る。`vbuf' ã¯æŠ½å‡ºã—ãŸãƒ‡ãƒ¼ã‚¿ã‚’書ã込むãƒãƒƒãƒ•ã‚¡ã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰ãƒãƒƒãƒ•ã‚¡ã«æ›¸ãè¾¼ã¾ã‚ŒãŸãƒ‡ãƒ¼ã‚¿ã®ã‚µã‚¤ã‚ºã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰ -1 ã§ã‚る。該当ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ãŒãªã„å ´åˆã‚‚ -1 ã‚’è¿”ã™ã€‚å–り出ãã†ã¨ã—ãŸå€¤ã®ã‚µã‚¤ã‚ºãŒ `start' よりå°ã•ã‹ã£ãŸå ´åˆã«ã¯è©²å½“ã¨ã¿ãªã•ãªã„。書ãè¾¼ã¿ç”¨ãƒãƒƒãƒ•ã‚¡ã®æœ«å°¾ã«çµ‚端文字ãŒè¿½åŠ ã•れãªã„ã“ã¨ã«æ³¨æ„ã™ã¹ãã§ã‚る。

レコードã®å€¤ã®ã‚µã‚¤ã‚ºã‚’å–å¾—ã™ã‚‹ã«ã¯ã€é–¢æ•° `crvsiz' を用ã„る。

int crvsiz(CURIA *curia, const char *kbuf, int ksiz);
`curia' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`kbuf' ã¯ã‚­ãƒ¼ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`ksiz' ã¯ã‚­ãƒ¼ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã‹ã€è² æ•°ãªã‚‰ `strlen(kbuf)' ã®å€¤ã¨ãªã‚‹ã€‚戻り値ã¯è©²å½“レコードã®å€¤ã®ã‚µã‚¤ã‚ºã§ã‚ã‚‹ãŒã€è©²å½“ãŒãªã„å ´åˆã‚„エラーã®å ´åˆã¯ -1 ã§ã‚る。ã“ã®é–¢æ•°ã¯ãƒ¬ã‚³ãƒ¼ãƒ‰ã®æœ‰ç„¡ã‚’調ã¹ã‚‹ã®ã«ã‚‚便利ã§ã‚る。`crget' ã¨é•ã£ã¦å®Ÿãƒ‡ãƒ¼ã‚¿ã‚’読ã¿è¾¼ã¾ãªã„ã®ã§åŠ¹çŽ‡ãŒã‚ˆã„。

データベースã®ã‚¤ãƒ†ãƒ¬ãƒ¼ã‚¿ã‚’åˆæœŸåŒ–ã™ã‚‹ã«ã¯ã€é–¢æ•° `criterinit' を用ã„る。

int criterinit(CURIA *curia);
`curia' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰çœŸã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰å½ã§ã‚る。イテレータã¯ã€ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«æ ¼ç´ã•れãŸå…¨ã¦ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’å‚ç…§ã™ã‚‹ãŸã‚ã«ç”¨ã„られる。

データベースã®ã‚¤ãƒ†ãƒ¬ãƒ¼ã‚¿ã‹ã‚‰æ¬¡ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã®ã‚­ãƒ¼ã‚’å–り出ã™ã«ã¯ã€é–¢æ•° `criternext' を用ã„る。

char *criternext(CURIA *curia, int *sp);
`curia' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`sp' ㌠`NULL' ã§ãªã‘れã°ã€ãã®å‚ç…§å…ˆã«æŠ½å‡ºã—ãŸé ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’æ ¼ç´ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰ã‚­ãƒ¼ã‚’æ ¼ç´ã—ãŸé ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰ `NULL' ã§ã‚ã‚‹ã€‚ã‚¤ãƒ†ãƒ¬ãƒ¼ã‚¿ãŒæœ€å¾Œã¾ã§ãã¦è©²å½“ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ãŒãªã„å ´åˆã‚‚ `NULL' ã‚’è¿”ã™ã€‚戻り値ã®é ˜åŸŸã¯ã€å®Ÿéš›ã«ã¯1ãƒã‚¤ãƒˆå¤šã確ä¿ã—ã¦çµ‚端文字ãŒç½®ã‹ã‚Œã‚‹ã®ã§ã€æ–‡å­—列ã¨ã—ã¦åˆ©ç”¨ã§ãる。戻り値ã®é ˜åŸŸã¯ `malloc' ã§ç¢ºä¿ã•れるã®ã§ã€ä¸è¦ã«ãªã£ãŸã‚‰ `free' ã§è§£æ”¾ã™ã‚‹ã¹ãã§ã‚る。ã“ã®é–¢æ•°ã‚’繰り返ã—ã¦å‘¼ã¶ã“ã¨ã«ã‚ˆã£ã¦å…¨ã¦ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’一度ãšã¤å‚ç…§ã™ã‚‹ã“ã¨ãŒã§ãる。ãŸã ã—ã€ç¹°ã‚Šè¿”ã—ã®é–“ã«ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®æ›´æ–°ãŒã‚ã£ãŸå ´åˆã¯ãã®é™ã‚Šã§ã¯ãªã„。ãªãŠã€å–り出ã™ãƒ¬ã‚³ãƒ¼ãƒ‰ã®é †åºã¯åˆ¶å¾¡ã§ããšã€æ ¼ç´ã—ãŸé †ç•ªã§ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’å–り出ã›ã‚‹ã¨ã¯é™ã‚‰ãªã„。

データベースã®ã‚¢ãƒ©ã‚¤ãƒ³ãƒ¡ãƒ³ãƒˆã‚’設定ã™ã‚‹ã«ã¯ã€é–¢æ•° `crsetalign' を用ã„る。

int crsetalign(CURIA *curia, int align);
`curia' ã¯ãƒ©ã‚¤ã‚¿ã§æŽ¥ç¶šã—ãŸãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`align' ã¯ã‚¢ãƒ©ã‚¤ãƒ³ãƒ¡ãƒ³ãƒˆã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰çœŸã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰å½ã§ã‚る。アラインメントを設定ã—ã¦ãŠãã¨ã€ãƒ¬ã‚³ãƒ¼ãƒ‰ã®ä¸Šæ›¸ãã‚’é »ç¹ã«ã™ã‚‹å ´åˆã®å‡¦ç†åŠ¹çŽ‡ãŒè‰¯ããªã‚‹ã€‚アラインメントã«ã¯ã€ä¸€é€£ã®æ›´æ–°æ“作をã—ãŸå¾Œã®çŠ¶æ…‹ã§ã®æ¨™æº–çš„ãªå€¤ã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã®ãŒã‚ˆã„ã€‚ã‚¢ãƒ©ã‚¤ãƒ³ãƒ¡ãƒ³ãƒˆãŒæ­£æ•°ã®å ´åˆã€ãƒ¬ã‚³ãƒ¼ãƒ‰ã®é ˜åŸŸã®ã‚µã‚¤ã‚ºãŒã‚¢ãƒ©ã‚¤ãƒ³ãƒ¡ãƒ³ãƒˆã®å€æ•°ã«ãªã‚‹ã‚ˆã†ã«ãƒ‘ディングãŒã¨ã‚‰ã‚Œã‚‹ã€‚アラインメントãŒè² æ•°ã®å ´åˆã€`vsiz' を値ã®ã‚µã‚¤ã‚ºã¨ã—ã¦ã€ãƒ‘ディングã®ã‚µã‚¤ã‚ºã¯ `(vsiz / pow(2, abs(align) - 1))' ã¨ã—ã¦ç®—出ã•れる。アラインメントã®è¨­å®šã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«ä¿å­˜ã•れãªã„ã®ã§ã€ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’é–‹ãåº¦ã«æŒ‡å®šã™ã‚‹å¿…è¦ãŒã‚る。

データベースã®ãƒ•リーブロックプールã®ã‚µã‚¤ã‚ºè¨­å®šã™ã‚‹ã«ã¯ã€é–¢æ•° `crsetfbpsiz' を用ã„る。

int crsetfbpsiz(CURIA *curia, int size);
`curia' ã¯ãƒ©ã‚¤ã‚¿ã§æŽ¥ç¶šã—ãŸãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`size' ã¯ãƒ•リーブロックプールã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰çœŸã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰å½ã§ã‚る。フリーブロックプールã®ãƒ‡ãƒ•ォルトã®ã‚µã‚¤ã‚ºã¯16ã§ã‚る。サイズをより大ããã™ã‚‹ã¨ã€ãƒ¬ã‚³ãƒ¼ãƒ‰ã®ä¸Šæ›¸ãを繰り返ã™éš›ã®ç©ºé–“効率ã¯ä¸ŠãŒã‚‹ãŒã€æ™‚間効率ãŒä¸‹ãŒã‚‹ã€‚

データベースを更新ã—ãŸå†…容をファイルã¨ãƒ‡ãƒã‚¤ã‚¹ã«åŒæœŸã•ã›ã‚‹ã«ã¯ã€é–¢æ•° `crsync' を用ã„る。

int crsync(CURIA *curia);
`curia' ã¯ãƒ©ã‚¤ã‚¿ã§æŽ¥ç¶šã—ãŸãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰çœŸã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰å½ã§ã‚る。ã“ã®é–¢æ•°ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’é–‰ã˜ãªã„ã†ã¡ã«åˆ¥ãƒ—ロセスã«ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルを利用ã•ã›ã‚‹å ´åˆã«å½¹ç«‹ã¤ã€‚

データベースを最é©åŒ–ã™ã‚‹ã«ã¯ã€é–¢æ•° `croptimize' を用ã„る。

int croptimize(CURIA *curia, int bnum);
`curia' ã¯ãƒ©ã‚¤ã‚¿ã§æŽ¥ç¶šã—ãŸãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`bnum' ã¯æ–°ãŸãªãƒã‚±ãƒƒãƒˆé…列ã®è¦ç´ æ•°ã‚’指定ã™ã‚‹ãŒã€0 以下ãªã‚‰ç¾åœ¨ã®ãƒ¬ã‚³ãƒ¼ãƒ‰æ•°ã«æœ€é©ãªå€¤ãŒæŒ‡å®šã•ã‚Œã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰çœŸã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰å½ã§ã‚る。レコードを削除ã—ãŸã‚Šã€ç½®æ›ãƒ¢ãƒ¼ãƒ‰ã‚„連çµãƒ¢ãƒ¼ãƒ‰ã§æ›¸ãè¾¼ã¿ã‚’繰り返ã—ãŸã‚Šã™ã‚‹å ´åˆã¯ã€ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹å†…ã«ä¸è¦ãªé ˜åŸŸãŒè“„ç©ã™ã‚‹ãŒã€ã“ã®é–¢æ•°ã¯ãれを解消ã™ã‚‹ã®ã«å½¹ç«‹ã¤ã€‚

データベースã®åå‰ã‚’å¾—ã‚‹ã«ã¯ã€é–¢æ•° `crname' を用ã„る。

char *crname(CURIA *curia);
`curia' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰åå‰ã‚’æ ¼ç´ã—ãŸé ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰ `NULL' ã§ã‚る。戻り値ã®é ˜åŸŸã¯ `malloc' ã§ç¢ºä¿ã•れるã®ã§ã€ä¸è¦ã«ãªã£ãŸã‚‰ `free' ã§è§£æ”¾ã™ã‚‹ã¹ãã§ã‚る。

データベースファイルã®ã‚µã‚¤ã‚ºã®åˆè¨ˆã‚’å¾—ã‚‹ã«ã¯ã€é–¢æ•° `crfsiz' を用ã„る。

int crfsiz(CURIA *curia);
`curia' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルã®ã‚µã‚¤ã‚ºã®åˆè¨ˆã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰ -1 ã§ã‚る。戻り値ãŒ2GBã‚’è¶ŠãˆãŸå ´åˆã¯æ¡æº¢ã‚ŒãŒèµ·ã“る。

データベースファイルã®ã‚µã‚¤ã‚ºã®åˆè¨ˆã‚’å€ç²¾åº¦æµ®å‹•å°æ•°ã¨ã—ã¦å¾—ã‚‹ã«ã¯ã€é–¢æ•° `crfsizd' を用ã„る。

double crfsizd(CURIA *curia);
`curia' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルã®ã‚µã‚¤ã‚ºã®åˆè¨ˆã®å€ç²¾åº¦å€¤ã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰ -1 ã§ã‚る。

データベースã®ãƒã‚±ãƒƒãƒˆé…列ã®è¦ç´ æ•°ã®åˆè¨ˆã‚’å¾—ã‚‹ã«ã¯ã€é–¢æ•° `crbnum' を用ã„る。

int crbnum(CURIA *curia);
`curia' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®ãƒã‚±ãƒƒãƒˆé…列ã®è¦ç´ æ•°ã®åˆè¨ˆã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰ -1 ã§ã‚る。

データベースã®ãƒã‚±ãƒƒãƒˆé…列ã®åˆ©ç”¨æ¸ˆã¿ã®è¦ç´ æ•°ã®åˆè¨ˆã‚’å¾—ã‚‹ã«ã¯ã€é–¢æ•° `crbusenum' を用ã„る。

int crbusenum(CURIA *curia);
`curia' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰ãƒã‚±ãƒƒãƒˆé…列ã®åˆ©ç”¨æ¸ˆã¿ã®è¦ç´ æ•°ã®åˆè¨ˆã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰ -1 ã§ã‚る。ã“ã®é–¢æ•°ã¯ãƒã‚±ãƒƒãƒˆé…列ã®å…¨ã¦ã®è¦ç´ ã‚’å‚ç…§ã™ã‚‹ã®ã§ã€åŠ¹çŽ‡ãŒæ‚ªã„。

データベースã®ãƒ¬ã‚³ãƒ¼ãƒ‰æ•°ã‚’å¾—ã‚‹ã«ã¯ã€é–¢æ•° `crrnum' を用ã„る。

int crrnum(CURIA *curia);
`curia' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®ãƒ¬ã‚³ãƒ¼ãƒ‰æ•°ã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰ -1 ã§ã‚る。

データベースãƒãƒ³ãƒ‰ãƒ«ãŒãƒ©ã‚¤ã‚¿ã‹ã©ã†ã‹ã‚’調ã¹ã‚‹ã«ã¯ã€é–¢æ•° `crwritable' を用ã„る。

int crwritable(CURIA *curia);
`curia' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚戻り値ã¯ãƒ©ã‚¤ã‚¿ãªã‚‰çœŸã§ã‚りã€ãã†ã§ãªã‘れã°å½ã§ã‚る。

データベースã«è‡´å‘½çš„エラーãŒèµ·ããŸã‹ã©ã†ã‹ã‚’調ã¹ã‚‹ã«ã¯ã€é–¢æ•° `crfatalerror' を用ã„る。

int crfatalerror(CURIA *curia);
`curia' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚戻り値ã¯è‡´å‘½çš„エラーãŒã‚れã°çœŸã§ã‚りã€ãã†ã§ãªã‘れã°å½ã§ã‚る。

データベースディレクトリã®inode番å·ã‚’å¾—ã‚‹ã«ã¯ã€é–¢æ•° `crinode' を用ã„る。

int crinode(CURIA *curia);
`curia' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚戻り値ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã®inode番å·ã§ã‚る。

ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®æœ€çµ‚更新時刻を得るã«ã¯ã€é–¢æ•° `crmtime' を用ã„る。

time_t crmtime(CURIA *curia);
`curia' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚戻り値ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®æœ€çµ‚更新時刻ã§ã‚る。

データベースディレクトリを削除ã™ã‚‹ã«ã¯ã€é–¢æ•° `crremove' を用ã„る。

int crremove(const char *name);
`name' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã®åå‰ã‚’指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰çœŸã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰å½ã§ã‚る。

壊れãŸãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã‚’修復ã™ã‚‹ã«ã¯ã€é–¢æ•° `crrepair' を用ã„る。

int crrepair(const char *name);
`name' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルã®åå‰ã‚’指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰çœŸã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰å½ã§ã‚る。修復ã•れãŸãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®å…¨ãƒ¬ã‚³ãƒ¼ãƒ‰ãŒå…ƒæ¥ã‚‚ã—ãã¯æœŸå¾…ã•ã‚Œã‚‹çŠ¶æ…‹ã«æˆ»ã‚‹ä¿è¨¼ã¯ãªã„。

å…¨ã¦ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’エンディアンéžä¾å­˜ã®ãƒ‡ãƒ¼ã‚¿ã¨ã—ã¦ãƒ€ãƒ³ãƒ—ã™ã‚‹ã«ã¯ã€é–¢æ•° `crexportdb' を用ã„る。

int crexportdb(CURIA *curia, const char *name);
`curia' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`name' ã¯å‡ºåŠ›ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã®åå‰ã‚’指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰çœŸã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰å½ã§ã‚る。

エンディアンéžä¾å­˜ãƒ‡ãƒ¼ã‚¿ã‹ã‚‰å…¨ã¦ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’ロードã™ã‚‹ã«ã¯ã€é–¢æ•° `crimportdb' を用ã„る。

int crimportdb(CURIA *curia, const char *name);
`curia' ã¯ãƒ©ã‚¤ã‚¿ã§æŽ¥ç¶šã—ãŸãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚データベースã¯ç©ºã§ãªã‘れã°ãªã‚‰ãªã„。`name' ã¯å…¥åŠ›ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã®åå‰ã‚’指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰çœŸã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰å½ã§ã‚る。

データベースディレクトリã‹ã‚‰ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’直接å–å¾—ã™ã‚‹ã«ã¯ã€é–¢æ•° `crsnaffle' を用ã„る。

char *crsnaffle(const char *name, const char *kbuf, int ksiz, int *sp);
`name' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã®åå‰ã‚’指定ã™ã‚‹ã€‚`kbuf' ã¯ã‚­ãƒ¼ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`ksiz' ã¯ã‚­ãƒ¼ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã‹ã€è² æ•°ãªã‚‰ `strlen(kbuf)' ã®å€¤ã¨ãªã‚‹ã€‚`start' ã¯å€¤ã®é ˜åŸŸã‹ã‚‰æŠ½å‡ºã™ã‚‹æœ€åˆã®ãƒã‚¤ãƒˆã®ã‚ªãƒ•セットを指定ã™ã‚‹ã€‚`max' ã¯å€¤ã®é ˜åŸŸã‹ã‚‰æŠ½å‡ºã™ã‚‹ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã‹ã€è² æ•°ãªã‚‰ç„¡åˆ¶é™ã¨ãªã‚‹ã€‚`sp' ㌠`NULL' ã§ãªã‘れã°ã€ãã®å‚ç…§å…ˆã«æŠ½å‡ºã—ãŸé ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’æ ¼ç´ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰å€¤ã‚’æ ¼ç´ã—ãŸé ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰ `NULL' ã§ã‚る。該当ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ãŒãªã„å ´åˆã‚‚ `NULL' ã‚’è¿”ã™ã€‚å–り出ãã†ã¨ã—ãŸå€¤ã®ã‚µã‚¤ã‚ºãŒ `start' よりå°ã•ã‹ã£ãŸå ´åˆã«ã¯è©²å½“ã¨ã¿ãªã•ãªã„。戻り値ã®é ˜åŸŸã¯ã€å®Ÿéš›ã«ã¯1ãƒã‚¤ãƒˆå¤šã確ä¿ã—ã¦çµ‚端文字ãŒç½®ã‹ã‚Œã‚‹ã®ã§ã€æ–‡å­—列ã¨ã—ã¦åˆ©ç”¨ã§ãる。戻り値ã®é ˜åŸŸã¯ `malloc' ã§ç¢ºä¿ã•れるã®ã§ã€ä¸è¦ã«ãªã£ãŸã‚‰ `free' ã§è§£æ”¾ã™ã‚‹ã¹ãã§ã‚る。ã“ã®é–¢æ•°ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªãŒåˆ¥ã®ãƒ—ロセスã«ãƒ­ãƒƒã‚¯ã•れã¦ã„ã¦ã‚‚利用ã§ãã‚‹ãŒã€æœ€æ–°ã®æ›´æ–°ãŒå映ã•れã¦ã„ã‚‹ä¿è¨¼ã¯ãªã„。

ラージオブジェクト用データベースã«ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’追加ã™ã‚‹ã«ã¯ã€é–¢æ•° `crputlob' を用ã„る。

int crputlob(CURIA *curia, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int dmode);
`curia' ã¯ãƒ©ã‚¤ã‚¿ã§æŽ¥ç¶šã—ãŸãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`kbuf' ã¯ã‚­ãƒ¼ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`ksiz' ã¯ã‚­ãƒ¼ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã‹ã€è² æ•°ãªã‚‰ `strlen(kbuf)' ã®å€¤ã¨ãªã‚‹ã€‚`vbuf' ã¯å€¤ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`vsiz' ã¯å€¤ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã‹ã€è² æ•°ãªã‚‰ `strlen(vbuf)' ã®å€¤ã¨ãªã‚‹ã€‚`dmode' ã¯ã‚­ãƒ¼ãŒæ—¢å­˜ãƒ¬ã‚³ãƒ¼ãƒ‰ã¨é‡è¤‡ã—ãŸéš›ã®åˆ¶å¾¡ã‚’指定ã™ã‚‹ã€‚`CR_DOVER' ã¯æ—¢å­˜ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã®å€¤ã‚’上書ãã—ã€`CR_DKEEP' ã¯æ—¢å­˜ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’残ã—ã¦ã‚¨ãƒ©ãƒ¼ã‚’è¿”ã—ã€`DP_DCAT' ã¯æŒ‡å®šã•れãŸå€¤ã‚’既存ã®å€¤ã®æœ«å°¾ã«åŠ ãˆã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰çœŸã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰å½ã§ã‚る。

ラージオブジェクト用データベースã‹ã‚‰ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’削除ã™ã‚‹ã«ã¯ã€é–¢æ•° `croutlob' を用ã„る。

int croutlob(CURIA *curia, const char *kbuf, int ksiz);
`curia' ã¯ãƒ©ã‚¤ã‚¿ã§æŽ¥ç¶šã—ãŸãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`kbuf' ã¯ã‚­ãƒ¼ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`ksiz' ã¯ã‚­ãƒ¼ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã‹ã€è² æ•°ãªã‚‰ `strlen(kbuf)' ã®å€¤ã¨ãªã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰çœŸã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰å½ã§ã‚る。該当ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ãŒãªã„å ´åˆã‚‚å½ã‚’è¿”ã™ã€‚

ラージオブジェクト用データベースã‹ã‚‰ãƒ¬ã‚³ãƒ¼ãƒ‰ã®å€¤ã‚’å–å¾—ã™ã‚‹ã«ã¯ã€é–¢æ•° `crgetlob' を用ã„る。

char *crgetlob(CURIA *curia, const char *kbuf, int ksiz, int start, int max, int *sp);
`curia' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`kbuf' ã¯ã‚­ãƒ¼ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`ksiz' ã¯ã‚­ãƒ¼ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã‹ã€è² æ•°ãªã‚‰ `strlen(kbuf)' ã®å€¤ã¨ãªã‚‹ã€‚`start' ã¯å€¤ã®é ˜åŸŸã‹ã‚‰æŠ½å‡ºã™ã‚‹æœ€åˆã®ãƒã‚¤ãƒˆã®ã‚ªãƒ•セットを指定ã™ã‚‹ã€‚`max' ã¯å€¤ã®é ˜åŸŸã‹ã‚‰æŠ½å‡ºã™ã‚‹ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã‹ã€è² æ•°ãªã‚‰ç„¡åˆ¶é™ã¨ãªã‚‹ã€‚`sp' ㌠`NULL' ã§ãªã‘れã°ã€ãã®å‚ç…§å…ˆã«æŠ½å‡ºã—ãŸé ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’æ ¼ç´ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰å€¤ã‚’æ ¼ç´ã—ãŸé ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰ `NULL' ã§ã‚る。該当ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ãŒãªã„å ´åˆã‚‚ `NULL' ã‚’è¿”ã™ã€‚å–り出ãã†ã¨ã—ãŸå€¤ã®ã‚µã‚¤ã‚ºãŒ `start' よりå°ã•ã‹ã£ãŸå ´åˆã«ã¯è©²å½“ã¨ã¿ãªã•ãªã„。戻り値ã®é ˜åŸŸã¯ã€å®Ÿéš›ã«ã¯1ãƒã‚¤ãƒˆå¤šã確ä¿ã—ã¦çµ‚端文字ãŒç½®ã‹ã‚Œã‚‹ã®ã§ã€æ–‡å­—列ã¨ã—ã¦åˆ©ç”¨ã§ãる。戻り値ã®é ˜åŸŸã¯ `malloc' ã§ç¢ºä¿ã•れるã®ã§ã€ä¸è¦ã«ãªã£ãŸã‚‰ `free' ã§è§£æ”¾ã™ã‚‹ã¹ãã§ã‚る。

ラージオブジェクト用データベースã«ã‚るレコードã®ãƒ•ァイルディスクリプタをå–å¾—ã™ã‚‹ã«ã¯ã€é–¢æ•° `crgetlobfd' を用ã„る。

int crgetlobfd(CURIA *curia, const char *kbuf, int ksiz);
`curia' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`kbuf' ã¯ã‚­ãƒ¼ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`ksiz' ã¯ã‚­ãƒ¼ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã‹ã€è² æ•°ãªã‚‰ `strlen(kbuf)' ã®å€¤ã¨ãªã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰è©²å½“ã®ãƒ•ァイルディスクリプタã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰ -1 ã§ã‚る。該当ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ãŒãªã„å ´åˆã‚‚ -1 ã‚’è¿”ã™ã€‚戻り値ã®ãƒ•ァイルディスクリプタ㯠`open' コールã§é–‹ã‹ã‚Œã‚‹ã€‚データベースãŒãƒ©ã‚¤ã‚¿ã§æŽ¥ç¶šã•れãŸå ´åˆã¯ãã®ãƒ‡ã‚£ã‚¹ã‚¯ãƒªãƒ—ã‚¿ã¯æ›¸ãè¾¼ã¿å¯èƒ½ï¼ˆO_RDWR)ã§ã‚りã€ãã†ã§ãªã‘ã‚Œã°æ›¸ãè¾¼ã¿ä¸å¯èƒ½ï¼ˆO_RDONLY)ã§ã‚る。ディスクリプタãŒä¸è¦ã«ãªã£ãŸã‚‰ `close' ã§é–‰ã˜ã‚‹ã¹ãã§ã‚る。

ラージオブジェクト用データベースã«ã‚るレコードã®å€¤ã®ã‚µã‚¤ã‚ºã‚’å–å¾—ã™ã‚‹ã«ã¯ã€é–¢æ•° `crvsizlob' を用ã„る。

int crvsizlob(CURIA *curia, const char *kbuf, int ksiz);
`curia' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`kbuf' ã¯ã‚­ãƒ¼ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`ksiz' ã¯ã‚­ãƒ¼ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã‹ã€è² æ•°ãªã‚‰ `strlen(kbuf)' ã®å€¤ã¨ãªã‚‹ã€‚戻り値ã¯è©²å½“レコードã®å€¤ã®ã‚µã‚¤ã‚ºã§ã‚りã€è©²å½“ãŒãªã„å ´åˆã‚„エラーã®å ´åˆã¯ -1 ã§ã‚る。ã“ã®é–¢æ•°ã¯ãƒ¬ã‚³ãƒ¼ãƒ‰ã®æœ‰ç„¡ã‚’調ã¹ã‚‹ã®ã«ã‚‚便利ã§ã‚る。`crgetlob' ã¨é•ã£ã¦å®Ÿãƒ‡ãƒ¼ã‚¿ã‚’読ã¿è¾¼ã¾ãªã„ã®ã§åŠ¹çŽ‡ãŒã‚ˆã„。

ラージオブジェクト用データベースã®ãƒ¬ã‚³ãƒ¼ãƒ‰æ•°ã®åˆè¨ˆã‚’å¾—ã‚‹ã«ã¯ã€é–¢æ•° `crrnumlob' を用ã„る。

int crrnumlob(CURIA *curia);
`curia' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®ãƒ¬ã‚³ãƒ¼ãƒ‰æ•°ã®åˆè¨ˆã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰ -1 ã§ã‚る。

サンプルコード

åå‰ã¨å¯¾å¿œã•ã›ã¦é›»è©±ç•ªå·ã‚’æ ¼ç´ã—ã€ãれを検索ã™ã‚‹ã‚¢ãƒ—リケーションã®ã‚µãƒ³ãƒ—ルコードを以下ã«ç¤ºã™ã€‚

#include <depot.h>
#include <curia.h>
#include <stdlib.h>
#include <stdio.h>

#define NAME     "mikio"
#define NUMBER   "000-1234-5678"
#define DBNAME   "book"

int main(int argc, char **argv){
  CURIA *curia;
  char *val;

  /* データベースを開ã */
  if(!(curia = cropen(DBNAME, CR_OWRITER | CR_OCREAT, -1, -1))){
    fprintf(stderr, "cropen: %s\n", dperrmsg(dpecode));
    return 1;
  }

  /* レコードを格ç´ã™ã‚‹ */
  if(!crput(curia, NAME, -1, NUMBER, -1, CR_DOVER)){
    fprintf(stderr, "crput: %s\n", dperrmsg(dpecode));
  }

  /* レコードをå–å¾—ã™ã‚‹ */
  if(!(val = crget(curia, NAME, -1, 0, -1, NULL))){
    fprintf(stderr, "crget: %s\n", dperrmsg(dpecode));
  } else {
    printf("Name: %s\n", NAME);
    printf("Number: %s\n", val);
    free(val);
  }

  /* データベースを閉ã˜ã‚‹ */
  if(!crclose(curia)){
    fprintf(stderr, "crclose: %s\n", dperrmsg(dpecode));
    return 1;
  }

  return 0;
}

データベースã®å…¨ã¦ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’表示ã™ã‚‹ã‚¢ãƒ—リケーションã®ã‚µãƒ³ãƒ—ルコードを以下ã«ç¤ºã™ã€‚

#include <depot.h>
#include <curia.h>
#include <stdlib.h>
#include <stdio.h>

#define DBNAME   "book"

int main(int argc, char **argv){
  CURIA *curia;
  char *key, *val;

  /* データベースを開ã */
  if(!(curia = cropen(DBNAME, CR_OREADER, -1, -1))){
    fprintf(stderr, "cropen: %s\n", dperrmsg(dpecode));
    return 1;
  }

  /* ã‚¤ãƒ†ãƒ¬ãƒ¼ã‚¿ã‚’åˆæœŸåŒ–ã™ã‚‹ */
  if(!criterinit(curia)){
    fprintf(stderr, "criterinit: %s\n", dperrmsg(dpecode));
  }

  /* イテレータを走査ã™ã‚‹ */
  while((key = criternext(curia, NULL)) != NULL){
    if(!(val = crget(curia, key, -1, 0, -1, NULL))){
      fprintf(stderr, "crget: %s\n", dperrmsg(dpecode));
      free(key);
      break;
    }
    printf("%s: %s\n", key, val);
    free(val);
    free(key);
  }

  /* データベースを閉ã˜ã‚‹ */
  if(!crclose(curia)){
    fprintf(stderr, "crclose: %s\n", dperrmsg(dpecode));
    return 1;
  }

  return 0;
}

注記

Curiaを利用ã—ãŸãƒ—ログラムをビルドã™ã‚‹æ–¹æ³•ã¯ã€Depotã®å ´åˆã¨å…¨ãåŒã˜ã§ã‚る。

gcc -I/usr/local/include -o sample sample.c -L/usr/local/lib -lqdbm

POSIXスレッドを有効ã«ã—ã¦QDBMをビルドã—ãŸå ´åˆã€å¤–部変数 `dpecode' ã¯ã‚¹ãƒ¬ãƒƒãƒ‰å›ºæœ‰ãƒ‡ãƒ¼ã‚¿ã¸ã®å‚ç…§ã¨ã—ã¦æ‰±ã‚れã€Curiaã®å„関数ã¯ãƒªã‚¨ãƒ³ãƒˆãƒ©ãƒ³ãƒˆã«ãªã‚‹ã€‚ãã®å ´åˆã€ã‚¹ãƒ¬ãƒƒãƒ‰é–“ã§åŒæ™‚ã«åŒã˜ãƒãƒ³ãƒ‰ãƒ«ã«ã‚¢ã‚¯ã‚»ã‚¹ã—ãªã„é™ã‚Šã¯ã€å„関数ã¯ã‚¹ãƒ¬ãƒƒãƒ‰ã‚»ãƒ¼ãƒ•ã§ã‚る。ãŸã ã—ã€`errno' ã‚„ `malloc' ç­‰ãŒã‚¹ãƒ¬ãƒƒãƒ‰ã‚»ãƒ¼ãƒ•ãªå‡¦ç†ç³»ã§ã‚ã‚‹ã“ã¨ãŒå‰æã¨ãªã‚‹ã€‚


Curia用コマンド

Curiaã«å¯¾å¿œã™ã‚‹ã‚³ãƒžãƒ³ãƒ‰ãƒ©ã‚¤ãƒ³ã‚¤ãƒ³ã‚¿ãƒ•ェースã¯ä»¥ä¸‹ã®ã‚‚ã®ã§ã‚る。

コマンド `crmgr' ã¯Curiaã‚„ãã®ã‚¢ãƒ—リケーションã®ãƒ‡ãƒãƒƒã‚°ã«å½¹ç«‹ã¤ãƒ„ールã§ã‚る。データベースを更新ã—ãŸã‚Šã€ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®çŠ¶æ…‹ã‚’èª¿ã¹ãŸã‚Šã™ã‚‹æ©Ÿèƒ½ã‚’æŒã¤ã€‚シェルスクリプトã§ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚¢ãƒ—リケーションを作るã®ã«ã‚‚利用ã§ãã‚‹ã€‚ä»¥ä¸‹ã®æ›¸å¼ã§ç”¨ã„る。`name' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹åã€`key' ã¯ãƒ¬ã‚³ãƒ¼ãƒ‰ã®ã‚­ãƒ¼ã€`val' ã¯ãƒ¬ã‚³ãƒ¼ãƒ‰ã®å€¤ã‚’指定ã™ã‚‹ã€‚

crmgr create [-s] [-bnum num] [-dnum num] name
データベースディレクトリを作æˆã™ã‚‹ã€‚
crmgr put [-kx|-ki] [-vx|-vi|-vf] [-keep|-cat] [-lob] [-na] name key val
キーã¨å€¤ã«å¯¾å¿œã™ã‚‹ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’追加ã™ã‚‹ã€‚
crmgr out [-kx|-ki] [-lob] name key
キーã«å¯¾å¿œã™ã‚‹ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’削除ã™ã‚‹ã€‚
crmgr get [-nl] [-kx|-ki] [-start num] [-max num] [-ox] [-lob] [-n] name key
キーã«å¯¾å¿œã™ã‚‹ãƒ¬ã‚³ãƒ¼ãƒ‰ã®å€¤ã‚’å–å¾—ã—ã¦æ¨™æº–出力ã™ã‚‹ã€‚
crmgr list [-nl] [-k|-v] [-ox] name
データベース内ã®å…¨ã¦ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã®ã‚­ãƒ¼ã¨å€¤ã‚’ã‚¿ãƒ–ã¨æ”¹è¡Œã§åŒºåˆ‡ã£ã¦æ¨™æº–出力ã™ã‚‹ã€‚
crmgr optimize [-bnum num] [-na] name
データベースを最é©åŒ–ã™ã‚‹ã€‚
crmgr inform [-nl] name
データベースã®é›‘å¤šãªæƒ…報を出力ã™ã‚‹ã€‚
crmgr remove name
データベースディレクトリを削除ã™ã‚‹ã€‚
crmgr repair name
壊れãŸãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã‚’修復ã™ã‚‹ã€‚
crmgr exportdb name dir
å…¨ã¦ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’エンディアンéžä¾å­˜ã®ãƒ‡ãƒ¼ã‚¿ã¨ã—ã¦ãƒ€ãƒ³ãƒ—ã™ã‚‹ã€‚
crmgr importdb [-bnum num] [-dnum num] name dir
エンディアンéžä¾å­˜ãƒ‡ãƒ¼ã‚¿ã‹ã‚‰å…¨ã¦ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’ロードã™ã‚‹ã€‚
crmgr snaffle [-kx|-ki] [-ox] [-n] name key
ロックã•れãŸãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‹ã‚‰ã‚­ãƒ¼ã«å¯¾å¿œã™ã‚‹ãƒ¬ã‚³ãƒ¼ãƒ‰ã®å€¤ã‚’å–å¾—ã—ã¦æ¨™æº–出力ã™ã‚‹ã€‚
crmgr version
QDBMã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³æƒ…報を標準出力ã™ã‚‹ã€‚

å„オプションã¯ä»¥ä¸‹ã®æ©Ÿèƒ½ã‚’æŒã¤ã€‚

  • -s : ファイルをスパースã«ã™ã‚‹ã€‚
  • -bnum num : ãƒã‚±ãƒƒãƒˆé…列ã®è¦ç´ æ•°ã‚’ `num' ã«æŒ‡å®šã™ã‚‹ã€‚
  • -dnum num : データベースファイルã®åˆ†å‰²æ•°ã‚’ `num' ã«æŒ‡å®šã™ã‚‹ã€‚
  • -kx : 2æ¡å˜ä½ã®16進数ã«ã‚ˆã‚‹ãƒã‚¤ãƒŠãƒªè¡¨ç¾ã¨ã—㦠`key' を扱ã†ã€‚
  • -ki : 10進数ã«ã‚ˆã‚‹æ•°å€¤è¡¨ç¾ã¨ã—㦠`key' を扱ã†ã€‚
  • -vx : 2æ¡å˜ä½ã®16進数ã«ã‚ˆã‚‹ãƒã‚¤ãƒŠãƒªè¡¨ç¾ã¨ã—㦠`val' を扱ã†ã€‚
  • -vi : 10進数ã«ã‚ˆã‚‹æ•°å€¤è¡¨ç¾ã¨ã—㦠`val' を扱ã†ã€‚
  • -vf : åå‰ãŒ `val' ã®ãƒ•ァイルã®ãƒ‡ãƒ¼ã‚¿ã‚’値ã¨ã—ã¦èª­ã¿è¾¼ã‚€ã€‚
  • -keep : 既存ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã¨ã‚­ãƒ¼ãŒé‡è¤‡æ™‚ã«ä¸Šæ›¸ãã›ãšã«ã‚¨ãƒ©ãƒ¼ã«ã™ã‚‹ã€‚
  • -cat : 既存ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã¨ã‚­ãƒ¼ãŒé‡è¤‡æ™‚ã«å€¤ã‚’末尾ã«è¿½åŠ ã™ã‚‹ã€‚
  • -na : アラインメントを設定ã—ãªã„。
  • -nl : ファイルロックをã‹ã‘ãšã«ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’é–‹ã。
  • -start : 値ã‹ã‚‰å–り出ã™ãƒ‡ãƒ¼ã‚¿ã®é–‹å§‹ã‚ªãƒ•セットを指定ã™ã‚‹ã€‚
  • -max : 値ã‹ã‚‰å–り出ã™ãƒ‡ãƒ¼ã‚¿ã®æœ€å¤§ã®é•·ã•を指定ã™ã‚‹ã€‚
  • -ox : 2æ¡å˜ä½ã®16進数ã«ã‚ˆã‚‹ãƒã‚¤ãƒŠãƒªè¡¨ç¾ã¨ã—ã¦æ¨™æº–出力を行ã†ã€‚
  • -lob : ラージオブジェクトを扱ã†ã€‚
  • -n : æ¨™æº–å‡ºåŠ›ã®æœ«å°¾ã«ä»˜åŠ ã•れる改行文字ã®å‡ºåŠ›ã‚’æŠ‘åˆ¶ã™ã‚‹ã€‚
  • -k : キーã®ã¿ã‚’出力ã™ã‚‹ã€‚
  • -v : 値ã®ã¿ã‚’出力ã™ã‚‹ã€‚

ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯å‡¦ç†ãŒæ­£å¸¸ã«çµ‚了ã™ã‚Œã° 0 ã‚’è¿”ã—ã€ã‚¨ãƒ©ãƒ¼ãŒã‚れã°ãれ以外ã®å€¤ã‚’è¿”ã—ã¦çµ‚了ã™ã‚‹ã€‚環境変数 `QDBMDBGFD' ã®å€¤ã¨ã—ã¦ã€å¤‰æ•° `dpecode' ã®å¤‰æ›´å±¥æ­´ã‚’出力ã™ã‚‹ãƒ•ァイルディスクリプタを指定ã“ã¨ãŒã§ãる。

コマンド `crtest' ã¯Curiaã®æ©Ÿèƒ½ãƒ†ã‚¹ãƒˆã‚„性能テストã«ç”¨ã„るツールã§ã‚る。`crtest' ã«ã‚ˆã£ã¦ç”Ÿæˆã•れãŸãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã‚’ `crmgr' ã«ã‚ˆã£ã¦è§£æžã—ãŸã‚Šã€`time' コマンドã«ã‚ˆã£ã¦ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã®å®Ÿè¡Œæ™‚間を計ã£ãŸã‚Šã™ã‚‹ã¨ã‚ˆã„ã€‚ä»¥ä¸‹ã®æ›¸å¼ã§ç”¨ã„る。`name' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹åã€`rnum' ã¯ãƒ¬ã‚³ãƒ¼ãƒ‰æ•°ã€`bnum' ã¯ãƒã‚±ãƒƒãƒˆé…列ã®è¦ç´ æ•°ã€`dnum' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルã®åˆ†å‰²æ•°ã€`pnum' ã¯ã‚­ãƒ¼ã®ãƒ‘ターン数ã€`align' ã¯ã‚¢ãƒ©ã‚¤ãƒ³ãƒ¡ãƒ³ãƒˆã®åŸºæœ¬ã‚µã‚¤ã‚ºã€`fbpsiz' ã¯ãƒ•リーブロックプールã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã€‚

crtest write [-s] [-lob] name rnum bnum dnum
`00000001'ã€`00000002' ã®ã‚ˆã†ã«å¤‰åŒ–ã™ã‚‹8ãƒã‚¤ãƒˆã®ã‚­ãƒ¼ã¨é©å½“ãª8ãƒã‚¤ãƒˆã®å€¤ã‚’連続ã—ã¦ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«è¿½åŠ ã™ã‚‹ã€‚
crtest read [-wb] [-lob] name
上記ã§ç”Ÿæˆã—ãŸãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®å…¨ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’検索ã™ã‚‹ã€‚
crtest rcat [-c] name rnum bnum dnum pnum align fbpsiz
キーãŒã‚る程度é‡è¤‡ã™ã‚‹ã‚ˆã†ã«ãƒ¬ã‚³ãƒ¼ãƒ‰ã®è¿½åŠ ã‚’è¡Œã„ã€é€£çµãƒ¢ãƒ¼ãƒ‰ã§å‡¦ç†ã™ã‚‹ã€‚
crtest combo name
å„種æ“作ã®çµ„ã¿åˆã‚ã›ãƒ†ã‚¹ãƒˆã‚’行ã†ã€‚
crtest wicked [-c] name rnum
å„種更新æ“作を無作為ã«é¸æŠžã—ã¦å®Ÿè¡Œã™ã‚‹ã€‚

å„オプションã¯ä»¥ä¸‹ã®æ©Ÿèƒ½ã‚’æŒã¤ã€‚

  • -s : ファイルをスパースã«ã™ã‚‹ã€‚
  • -lob : ラージオブジェクトを扱ã†ã€‚
  • -wb : 関数 `crget' ã®ä»£ã‚りã«é–¢æ•° `crgetwb' を用ã„る。
  • -c : Cabinã®ãƒžãƒƒãƒ—を使ã£ã¦æ¯”較テストを行ã†ã€‚

ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯å‡¦ç†ãŒæ­£å¸¸ã«çµ‚了ã™ã‚Œã° 0 ã‚’è¿”ã—ã€ã‚¨ãƒ©ãƒ¼ãŒã‚れã°ãれ以外ã®å€¤ã‚’è¿”ã—ã¦çµ‚了ã™ã‚‹ã€‚環境変数 `QDBMDBGFD' ã®å€¤ã¨ã—ã¦ã€å¤‰æ•° `dpecode' ã®å¤‰æ›´å±¥æ­´ã‚’出力ã™ã‚‹ãƒ•ァイルディスクリプタを指定ã“ã¨ãŒã§ãる。

コマンド `crtsv' ã¯ã‚¿ãƒ–区切りã§ã‚­ãƒ¼ã¨å€¤ã‚’表ç¾ã—ãŸè¡Œã‹ã‚‰ãªã‚‹TSVファイルã¨Curiaã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’相互変æ›ã™ã‚‹ã€‚ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€QDBMã®ä»–ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã‚„ä»–ã®DBMã¨ã®é–“ã§ãƒ‡ãƒ¼ã‚¿ã®äº¤æ›ã‚’行ã†éš›ã«å½¹ç«‹ã¤ã€‚ã¾ãŸã€ãƒã‚¤ãƒˆã‚ªãƒ¼ãƒ€ã®é•ã†ã‚·ã‚¹ãƒ†ãƒ ã®é–“ã§ãƒ‡ãƒ¼ã‚¿ã‚’交æ›ã™ã‚‹éš›ã«ã‚‚役立ã¤ã€‚ä»¥ä¸‹ã®æ›¸å¼ã§ç”¨ã„る。`name' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹åを指定ã™ã‚‹ã€‚`export' サブコマンドã§ã¯TSVã®ãƒ‡ãƒ¼ã‚¿ã¯æ¨™æº–入力ã‹ã‚‰èª­ã¿è¾¼ã‚€ã€‚キーãŒé‡è¤‡ã™ã‚‹ãƒ¬ã‚³ãƒ¼ãƒ‰ã¯å¾Œè€…を優先ã™ã‚‹ã€‚`-bnum' オプションã®å¼•æ•° `num' ã¯ãƒã‚±ãƒƒãƒˆé…列ã®è¦ç´ æ•°ã‚’指定ã™ã‚‹ã€‚`-dnum' オプションã®å¼•æ•° `num' ã¯è¦ç´ ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®æ•°ã‚’指定ã™ã‚‹ã€‚`import' サブコマンドã§ã¯TSVã®ãƒ‡ãƒ¼ã‚¿ãŒæ¨™æº–å‡ºåŠ›ã«æ›¸ã出ã•れる。

crtsv import [-bnum num] [-dnum num] [-bin] name
TSVファイルを読ã¿è¾¼ã‚“ã§ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’作æˆã™ã‚‹ã€‚
crtsv export [-bin] name
データベースã®å…¨ã¦ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’TSVファイルã¨ã—ã¦å‡ºåŠ›ã™ã‚‹ã€‚

å„オプションã¯ä»¥ä¸‹ã®æ©Ÿèƒ½ã‚’æŒã¤ã€‚

  • -bnum num : ãƒã‚±ãƒƒãƒˆé…列ã®è¦ç´ æ•°ã‚’ `num' ã«æŒ‡å®šã™ã‚‹ã€‚
  • -dnum num : データベースファイルã®åˆ†å‰²æ•°ã‚’ `num' ã«æŒ‡å®šã™ã‚‹ã€‚
  • -bin : Base64å½¢å¼ã§ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’扱ã†ã€‚

ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯å‡¦ç†ãŒæ­£å¸¸ã«çµ‚了ã™ã‚Œã° 0 ã‚’è¿”ã—ã€ã‚¨ãƒ©ãƒ¼ãŒã‚れã°ãれ以外ã®å€¤ã‚’è¿”ã—ã¦çµ‚了ã™ã‚‹ã€‚

Curiaã®ã‚³ãƒžãƒ³ãƒ‰ç¾¤ã‚’駆使ã™ã‚‹ã¨ã€ç°¡å˜ãªãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚·ã‚¹ãƒ†ãƒ ãŒæ§‹ç¯‰ã§ãる。例ãˆã° `/etc/password' をユーザåã§æ¤œç´¢ã™ã‚‹ãŸã‚ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’作æˆã™ã‚‹ã«ã¯ã€ä»¥ä¸‹ã®ã‚ˆã†ã«ã™ã‚‹ã€‚

cat /etc/passwd | tr ':' '\t' | crtsv import casket

ãã—ã¦ã€`mikio' ã¨ã„ã†ãƒ¦ãƒ¼ã‚¶ã®æƒ…報をå–り出ã™ã«ã¯ã€ä»¥ä¸‹ã®ã‚ˆã†ã«ã™ã‚‹ã€‚

crmgr get casket mikio

ã“れらã®ã‚³ãƒžãƒ³ãƒ‰ã¨åŒç­‰ã®æ©Ÿèƒ½ã‚’Curiaã®APIを用ã„ã¦å®Ÿè£…ã™ã‚‹ã“ã¨ã‚‚容易ã§ã‚る。


Relic: NDBM互æ›API

概è¦

Relicã¯ã€NDBMã¨äº’æ›ã™ã‚‹APIã§ã‚る。ã™ãªã‚ã¡ã€Depotã®é–¢æ•°ç¾¤ã‚’NDBMã®APIã§åŒ…ã‚“ã ã‚‚ã®ã§ã‚る。Relicを使ã£ã¦NDBMã®ã‚¢ãƒ—リケーションをQDBMã«ç§»æ¤ã™ã‚‹ã®ã¯ãŸã‚„ã™ã„。ã»ã¨ã‚“ã©ã®å ´åˆã€ã‚¤ãƒ³ã‚¯ãƒ«ãƒ¼ãƒ‰ã™ã‚‹ãƒ˜ãƒƒãƒ€ãƒ•ァイルを `ndbm.h' ã‹ã‚‰ `relic.h' ã«æ›ãˆã€ãƒ“ルドã®éš›ã®ãƒªãƒ³ã‚«ã‚ªãƒ—ションを `-lndbm' ã‹ã‚‰ `-lqdbm' ã«æ›ãˆã‚‹ã ã‘ã§ã‚ˆã„。

オリジナルã®NDBMã§ã¯ã€ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã¯äºŒã¤ã®ãƒ•ァイルã®å¯¾ã‹ã‚‰ãªã‚‹ã€‚ã²ã¨ã¤ã¯æŽ¥å°¾è¾žã« `.dir' ãŒã¤ãåå‰ã§ã€ã‚­ãƒ¼ã®ãƒ“ットマップを格ç´ã™ã‚‹ã€Œãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªãƒ•ァイルã€ã§ã‚る。もã†ã²ã¨ã¤ã¯æŽ¥å°¾è¾žã« `.pag' ãŒã¤ãåå‰ã§ã€ãƒ‡ãƒ¼ã‚¿ã®å®Ÿä½“ã‚’æ ¼ç´ã™ã‚‹ã€Œãƒ‡ãƒ¼ã‚¿ãƒ•ァイルã€ã§ã‚る。Relicã§ã¯ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªãƒ•ァイルã¯å˜ãªã‚‹ãƒ€ãƒŸãƒ¼ã¨ã—ã¦ä½œæˆã—ã€ãƒ‡ãƒ¼ã‚¿ãƒ•ァイルをデータベースã¨ã™ã‚‹ã€‚Relicã§ã¯ã‚ªãƒªã‚¸ãƒŠãƒ«ã®NDBMã¨é•ã„ã€æ ¼ç´ã™ã‚‹ãƒ‡ãƒ¼ã‚¿ã®ã‚µã‚¤ã‚ºã«åˆ¶é™ã¯ãªã„。ãªãŠã€ã‚ªãƒªã‚¸ãƒŠãƒ«ã®NDBMã§ç”Ÿæˆã—ãŸãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルをRelicã§æ‰±ã†ã“ã¨ã¯ã§ããªã„。

Relicを使ã†ãŸã‚ã«ã¯ã€`relic.h' 㨠`stdlib.h' 㨠`sys/types.h' 㨠`sys/stat.h' 㨠`fcntl.h' をインクルードã™ã¹ãã§ã‚る。通常ã€ã‚½ãƒ¼ã‚¹ãƒ•ァイルã®å†’頭付近ã§ä»¥ä¸‹ã®è¨˜è¿°ã‚’行ã†ã€‚

#include <relic.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

Relicã§ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’扱ã†éš›ã«ã¯ã€`DBM' åž‹ã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’ãƒãƒ³ãƒ‰ãƒ«ã¨ã—ã¦ç”¨ã„る。ãƒãƒ³ãƒ‰ãƒ«ã¯ã€é–¢æ•° `dbm_open' ã§é–‹ãã€é–¢æ•° `dbm_close' ã§é–‰ã˜ã‚‹ã€‚ãƒãƒ³ãƒ‰ãƒ«ã®ãƒ¡ãƒ³ãƒã‚’直接å‚ç…§ã™ã‚‹ã“ã¨ã¯æŽ¨å¥¨ã•れãªã„。

API

ãƒ‡ãƒ¼ã‚¿ã®æ ¼ç´ã€å‰Šé™¤ã€æ¤œç´¢ã«ç”¨ã„る関数ã¨ã®ãƒ‡ãƒ¼ã‚¿ã®æŽˆå—ã«ã¯ã€ã‚­ãƒ¼ã¨å€¤ã‚’表ç¾ã™ã‚‹ã®ã« `datum' åž‹ã®æ§‹é€ ä½“を用ã„る。

typedef struct { void *dptr; size_t dsize; } datum;
`dptr' ã¯ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã§ã‚る。`dsize' ã¯ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã®ã‚µã‚¤ã‚ºã§ã‚る。

データベースã®ãƒãƒ³ãƒ‰ãƒ«ã‚’作æˆã™ã‚‹ã«ã¯ã€é–¢æ•° `dbm_open' を用ã„る。

DBM *dbm_open(char *name, int flags, int mode);
`name' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®åå‰ã‚’指定ã™ã‚‹ãŒã€ãƒ•ァイルåã¯ãã‚Œã«æŽ¥å°¾è¾žã‚’ã¤ã‘ãŸã‚‚ã®ã«ãªã‚‹ã€‚`flags' 㯠`open' ã‚³ãƒ¼ãƒ«ã«æ¸¡ã™ã‚‚ã®ã¨åŒã˜ã ãŒã€`O_WRONLY' 㯠`O_RDWR' ã¨åŒã˜ã«ãªã‚Šã€è¿½åŠ ãƒ•ãƒ©ã‚°ã§ã¯ `O_CREAT' 㨠`O_TRUNC' ã®ã¿ãŒæœ‰åйã§ã‚る。`mode' 㯠`open' ã‚³ãƒ¼ãƒ«ã«æ¸¡ã™ã‚‚ã®ã¨åŒã˜ã§ãƒ•ァイルã®ãƒ¢ãƒ¼ãƒ‰ã‚’指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰ `NULL' ã§ã‚る。

データベースã¨ã®æŽ¥ç¶šã‚’é–‰ã˜ã¦ãƒãƒ³ãƒ‰ãƒ«ã‚’破棄ã™ã‚‹ã«ã¯ã€é–¢æ•° `dbm_close' を用ã„る。

void dbm_close(DBM *db);
`db' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚é–‰ã˜ãŸãƒãƒ³ãƒ‰ãƒ«ã®é ˜åŸŸã¯è§£æ”¾ã•れるã®ã§ã€ä»¥å¾Œã¯åˆ©ç”¨ã™ã‚‹ã“ã¨ãŒã§ããªããªã‚‹ã€‚

レコードを追加ã™ã‚‹ã«ã¯ã€é–¢æ•° `dbm_store' を用ã„る。

int dbm_store(DBM *db, datum key, datum content, int flags);
`db' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`key' ã¯ã‚­ãƒ¼ã®æ§‹é€ ä½“を指定ã™ã‚‹ã€‚`content' ã¯å€¤ã®æ§‹é€ ä½“を指定ã™ã‚‹ã€‚`frags' ㌠`DBM_INSERT' ãªã‚‰ã‚­ãƒ¼ã®é‡è¤‡æ™‚ã«æ›¸ãè¾¼ã¿ã‚’断念ã—ã€`DBM_REPLACE' ãªã‚‰ä¸Šæ›¸ãを行ã†ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰ 0 ã§ã‚りã€é‡è¤‡ã§ã®æ–­å¿µãªã‚‰ 1 ã§ã‚りã€ãã®ä»–ã®ã‚¨ãƒ©ãƒ¼ãªã‚‰ -1 ã§ã‚る。

レコードを削除ã™ã‚‹ã«ã¯ã€é–¢æ•° `dbm_delete' を用ã„る。

int dbm_delete(DBM *db, datum key);
`db' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`key' ã¯ã‚­ãƒ¼ã®æ§‹é€ ä½“を指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰ 0 ã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰ -1 ã§ã‚る。

レコードをå–å¾—ã™ã‚‹ã«ã¯ã€é–¢æ•° `dbm_fetch' を用ã„る。

datum dbm_fetch(DBM *db, datum key);
`db' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`key' ã¯ã‚­ãƒ¼ã®æ§‹é€ ä½“を指定ã™ã‚‹ã€‚戻り値ã¯å€¤ã®æ§‹é€ ä½“ã§ã‚る。該当ãŒã‚れã°ãƒ¡ãƒ³ãƒ `dptr' ãŒãã®é ˜åŸŸã‚’指ã—ã€ãƒ¡ãƒ³ãƒ `dsize' ãŒãã®ã‚µã‚¤ã‚ºã‚’示ã™ã€‚該当ãŒãªã‘れ㰠`dptr' ã®å€¤ã¯ `NULL' ã¨ãªã‚‹ã€‚`dptr' ã®æŒ‡ã™é ˜åŸŸã¯ãƒãƒ³ãƒ‰ãƒ«ã«é–¢é€£ã¥ã‘られã¦ç¢ºä¿ã•れã€åŒã˜ãƒãƒ³ãƒ‰ãƒ«ã«å¯¾ã—ã¦æ¬¡ã«ã“ã®é–¢æ•°ã‚’呼ã³å‡ºã™ã‹ã€ãƒãƒ³ãƒ‰ãƒ«ã‚’é–‰ã˜ã‚‹ã¾ã§ã€æœ‰åйãªãƒ‡ãƒ¼ã‚¿ã‚’ä¿æŒã™ã‚‹ã€‚

最åˆã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã®ã‚­ãƒ¼ã‚’å¾—ã‚‹ã«ã¯ã€é–¢æ•° `dbm_firstkey' を用ã„る。

datum dbm_firstkey(DBM *db);
`db' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚戻り値ã¯ã‚­ãƒ¼ã®æ§‹é€ ä½“ã§ã‚る。該当ãŒã‚れã°ãƒ¡ãƒ³ãƒ `dptr' ãŒãã®é ˜åŸŸã‚’指ã—ã€`dsize' ãŒãã®ã‚µã‚¤ã‚ºã‚’示ã™ã€‚該当ãŒãªã‘れ㰠`dptr' ã®å€¤ã¯ `NULL' ã¨ãªã‚‹ã€‚`dptr' ã®æŒ‡ã™é ˜åŸŸã¯ãƒãƒ³ãƒ‰ãƒ«ã«é–¢é€£ã¥ã‘られã¦ç¢ºä¿ã•れã€åŒã˜ãƒãƒ³ãƒ‰ãƒ«ã«å¯¾ã—ã¦æ¬¡ã«ã“ã®é–¢æ•°ã‚‚ã—ãã¯é–¢æ•° `dbm_nextkey' を呼ã³å‡ºã™ã‹ã€ãƒãƒ³ãƒ‰ãƒ«ã‚’é–‰ã˜ã‚‹ã¾ã§ã€æœ‰åйãªãƒ‡ãƒ¼ã‚¿ã‚’ä¿æŒã™ã‚‹ã€‚

次レコードã®ã‚­ãƒ¼ã‚’å¾—ã‚‹ã«ã¯ã€é–¢æ•° `dbm_nextkey' を用ã„る。

datum dbm_nextkey(DBM *db);
`db' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚戻り値ã¯ã‚­ãƒ¼ã®æ§‹é€ ä½“ã§ã‚る。該当ãŒã‚れã°ãƒ¡ãƒ³ãƒ `dptr' ãŒãã®é ˜åŸŸã‚’指ã—ã€`dsize' ãŒãã®ã‚µã‚¤ã‚ºã‚’示ã™ã€‚該当ãŒãªã‘れ㰠`dptr' ã®å€¤ã¯ `NULL' ã¨ãªã‚‹ã€‚`dptr' ã®æŒ‡ã™é ˜åŸŸã¯ãƒãƒ³ãƒ‰ãƒ«ã«é–¢é€£ã¥ã‘られã¦ç¢ºä¿ã•れã€åŒã˜ãƒãƒ³ãƒ‰ãƒ«ã«å¯¾ã—ã¦æ¬¡ã«ã“ã®é–¢æ•°ã‚‚ã—ãã¯é–¢æ•° `dbm_firstkey' を呼ã³å‡ºã™ã‹ã€ãƒãƒ³ãƒ‰ãƒ«ã‚’é–‰ã˜ã‚‹ã¾ã§ã€æœ‰åйãªãƒ‡ãƒ¼ã‚¿ã‚’ä¿æŒã™ã‚‹ã€‚

データベースã«è‡´å‘½çš„エラーãŒèµ·ããŸã‹ã©ã†ã‹ã‚’調ã¹ã‚‹ã«ã¯ã€é–¢æ•° `dbm_error' を用ã„る。

int dbm_error(DBM *db);
`db' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚戻り値ã¯è‡´å‘½çš„エラーãŒã‚れã°çœŸã§ã‚りã€ãã†ã§ãªã‘れã°å½ã§ã‚る。

関数 `dbm_clearerr' ã¯ä½•ã‚‚ã—ãªã„。

int dbm_clearerr(DBM *db);
`db' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚戻り値㯠0 ã§ã‚る。ã“ã®é–¢æ•°ã¯äº’æ›æ€§ã®ãŸã‚ã«ã®ã¿å­˜åœ¨ã™ã‚‹ã€‚

データベースãŒèª­ã¿è¾¼ã¿å°‚用ã‹ã©ã†ã‹ã‚’調ã¹ã‚‹ã«ã¯ã€é–¢æ•° `dbm_rdonly' を用ã„る。

int dbm_rdonly(DBM *db);
`db' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚戻り値ã¯èª­ã¿è¾¼ã¿å°‚用ãªã‚‰çœŸã§ã‚りã€ãã†ã§ãªã‘れã°å½ã§ã‚る。

ディレクトリファイルã®ãƒ•ァイルディスクリプタを得るã«ã¯ã€é–¢æ•° `dbm_dirfno' を用ã„る。

int dbm_dirfno(DBM *db);
`db' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚戻り値ã¯ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªãƒ•ァイルã®ãƒ•ァイルディスクリプタã§ã‚る。

データファイルã®ãƒ•ァイルディスクリプタを得るã«ã¯ã€é–¢æ•° `dbm_pagfno' を用ã„る。

int dbm_pagfno(DBM *db);
`db' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚戻り値ã¯ãƒ‡ãƒ¼ã‚¿ãƒ•ァイルã®ãƒ•ァイルディスクリプタã§ã‚る。

サンプルコード

åå‰ã¨å¯¾å¿œã•ã›ã¦é›»è©±ç•ªå·ã‚’æ ¼ç´ã—ã€ãれを検索ã™ã‚‹ã‚¢ãƒ—リケーションã®ã‚µãƒ³ãƒ—ルコードを以下ã«ç¤ºã™ã€‚

#include <relic.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <string.h>

#define NAME     "mikio"
#define NUMBER   "000-1234-5678"
#define DBNAME   "book"

int main(int argc, char **argv){
  DBM *db;
  datum key, val;
  int i;

  /* データベースを開ã */
  if(!(db = dbm_open(DBNAME, O_RDWR | O_CREAT, 00644))){
    perror("dbm_open");
    return 1;
  }

  /* レコードを準備ã™ã‚‹ */
  key.dptr = NAME;
  key.dsize = strlen(NAME);
  val.dptr = NUMBER;
  val.dsize = strlen(NUMBER);

  /* レコードを格ç´ã™ã‚‹ */
  if(dbm_store(db, key, val, DBM_REPLACE) != 0){
    perror("dbm_store");
  }

  /* レコードを検索ã™ã‚‹ */
  val = dbm_fetch(db, key);
  if(val.dptr){
    printf("Name: %s\n", NAME);
    printf("Number: ");
    for(i = 0; i < val.dsize; i++){
      putchar(((char *)val.dptr)[i]);
    }
    putchar('\n');
  } else {
    perror("dbm_fetch");
  }

  /* データベースを閉ã˜ã‚‹ */
  dbm_close(db);

  return 0;
}

注記

Relicを利用ã—ãŸãƒ—ログラムをビルドã™ã‚‹æ–¹æ³•ã¯ã€Depotã®å ´åˆã¨å…¨ãåŒã˜ã§ã‚ã‚‹ã€‚ãƒªãƒ³ã‚«ã«æ¸¡ã™ã‚ªãƒ—ション㯠`-lndbm' ã§ã¯ãªã `-lqdbm' ã§ã‚る。

gcc -I/usr/local/include -o sample sample.c -L/usr/local/lib -lqdbm

スレッド間ã§åŒæ™‚ã«åŒã˜ãƒãƒ³ãƒ‰ãƒ«ã«ã‚¢ã‚¯ã‚»ã‚¹ã—ãªã„é™ã‚Šã¯ã€Relicã®å„関数ã¯ã‚¹ãƒ¬ãƒƒãƒ‰ã‚»ãƒ¼ãƒ•ã§ã‚る。ãŸã ã—ã€`errno' ã‚„ `malloc' ç­‰ãŒã‚¹ãƒ¬ãƒƒãƒ‰ã‚»ãƒ¼ãƒ•ãªå‡¦ç†ç³»ã§ã‚ã‚‹ã“ã¨ãŒå‰æã¨ãªã‚‹ã€‚


Relic用コマンド

Relicã«å¯¾å¿œã™ã‚‹ã‚³ãƒžãƒ³ãƒ‰ãƒ©ã‚¤ãƒ³ã‚¤ãƒ³ã‚¿ãƒ•ェースã¯ä»¥ä¸‹ã®ã‚‚ã®ã§ã‚る。

コマンド `rlmgr' ã¯Relicã‚„ãã®ã‚¢ãƒ—リケーションã®ãƒ‡ãƒãƒƒã‚°ã«å½¹ç«‹ã¤ãƒ„ールã§ã‚る。データベースを更新ã—ãŸã‚Šã€ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®çŠ¶æ…‹ã‚’èª¿ã¹ãŸã‚Šã™ã‚‹æ©Ÿèƒ½ã‚’æŒã¤ã€‚シェルスクリプトã§ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚¢ãƒ—リケーションを作るã®ã«ã‚‚利用ã§ãã‚‹ã€‚ä»¥ä¸‹ã®æ›¸å¼ã§ç”¨ã„る。`name' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹åã€`key' ã¯ãƒ¬ã‚³ãƒ¼ãƒ‰ã®ã‚­ãƒ¼ã€`val' ã¯ãƒ¬ã‚³ãƒ¼ãƒ‰ã®å€¤ã‚’指定ã™ã‚‹ã€‚

rlmgr create name
データベースファイルを作æˆã™ã‚‹ã€‚
rlmgr store [-kx] [-vx|-vf] [-insert] name key val
キーã¨å€¤ã«å¯¾å¿œã™ã‚‹ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’追加ã™ã‚‹ã€‚
rlmgr delete [-kx] name key
キーã«å¯¾å¿œã™ã‚‹ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’削除ã™ã‚‹ã€‚
rlmgr fetch [-kx] [-ox] [-n] name key
キーã«å¯¾å¿œã™ã‚‹ãƒ¬ã‚³ãƒ¼ãƒ‰ã®å€¤ã‚’å–å¾—ã—ã¦æ¨™æº–出力ã™ã‚‹ã€‚
rlmgr list [-ox] name
データベース内ã®å…¨ã¦ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã®ã‚­ãƒ¼ã¨å€¤ã‚’ã‚¿ãƒ–ã¨æ”¹è¡Œã§åŒºåˆ‡ã£ã¦æ¨™æº–出力ã™ã‚‹ã€‚

å„オプションã¯ä»¥ä¸‹ã®æ©Ÿèƒ½ã‚’æŒã¤ã€‚

  • -kx : 2æ¡å˜ä½ã®16進数ã«ã‚ˆã‚‹ãƒã‚¤ãƒŠãƒªè¡¨ç¾ã¨ã—㦠`key' を扱ã†ã€‚
  • -vx : 2æ¡å˜ä½ã®16進数ã«ã‚ˆã‚‹ãƒã‚¤ãƒŠãƒªè¡¨ç¾ã¨ã—㦠`val' を扱ã†ã€‚
  • -vf : åå‰ãŒ `val' ã®ãƒ•ァイルã®ãƒ‡ãƒ¼ã‚¿ã‚’値ã¨ã—ã¦èª­ã¿è¾¼ã‚€ã€‚
  • -insert : 既存ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã¨ã‚­ãƒ¼ãŒé‡è¤‡æ™‚ã«ä¸Šæ›¸ãã›ãšã«ã‚¨ãƒ©ãƒ¼ã«ã™ã‚‹ã€‚
  • -ox : 2æ¡å˜ä½ã®16進数ã«ã‚ˆã‚‹ãƒã‚¤ãƒŠãƒªè¡¨ç¾ã¨ã—ã¦æ¨™æº–出力を行ã†ã€‚
  • -n : æ¨™æº–å‡ºåŠ›ã®æœ«å°¾ã«ä»˜åŠ ã•れる改行文字ã®å‡ºåŠ›ã‚’æŠ‘åˆ¶ã™ã‚‹ã€‚

ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯å‡¦ç†ãŒæ­£å¸¸ã«çµ‚了ã™ã‚Œã° 0 ã‚’è¿”ã—ã€ã‚¨ãƒ©ãƒ¼ãŒã‚れã°ãれ以外ã®å€¤ã‚’è¿”ã—ã¦çµ‚了ã™ã‚‹ã€‚

コマンド `rltest' ã¯Relicã®æ©Ÿèƒ½ãƒ†ã‚¹ãƒˆã‚„性能テストã«ç”¨ã„るツールã§ã‚る。ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã«ã‚ˆã£ã¦ç”Ÿæˆã•れãŸãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルを `rlmgr' ã«ã‚ˆã£ã¦è§£æžã—ãŸã‚Šã€`time' コマンドã«ã‚ˆã£ã¦ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã®å®Ÿè¡Œæ™‚間を計ã£ãŸã‚Šã™ã‚‹ã¨ã‚ˆã„ã€‚ä»¥ä¸‹ã®æ›¸å¼ã§ç”¨ã„る。`name' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹åã€`rnum' ã¯ãƒ¬ã‚³ãƒ¼ãƒ‰æ•°ã‚’指定ã™ã‚‹ã€‚

rltest write name rnum
`00000001'ã€`00000002' ã®ã‚ˆã†ã«å¤‰åŒ–ã™ã‚‹8ãƒã‚¤ãƒˆã®ã‚­ãƒ¼ã¨é©å½“ãª8ãƒã‚¤ãƒˆã®å€¤ã‚’連続ã—ã¦ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«è¿½åŠ ã™ã‚‹ã€‚
rltest read name rnum
上記ã§ç”Ÿæˆã—ãŸãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’検索ã™ã‚‹ã€‚

ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯å‡¦ç†ãŒæ­£å¸¸ã«çµ‚了ã™ã‚Œã° 0 ã‚’è¿”ã—ã€ã‚¨ãƒ©ãƒ¼ãŒã‚れã°ãれ以外ã®å€¤ã‚’è¿”ã—ã¦çµ‚了ã™ã‚‹ã€‚


Hovel: GDBM互æ›API

概è¦

Hovelã¯ã€GDBMã¨äº’æ›ã™ã‚‹APIã§ã‚る。ã™ãªã‚ã¡ã€DepotãŠã‚ˆã³Curiaã®é–¢æ•°ç¾¤ã‚’GDBMã®APIã§åŒ…ã‚“ã ã‚‚ã®ã§ã‚る。Hovelを使ã£ã¦GDBMã®ã‚¢ãƒ—リケーションをQDBMã«ç§»æ¤ã™ã‚‹ã®ã¯ãŸã‚„ã™ã„。ã»ã¨ã‚“ã©ã®å ´åˆã€ã‚¤ãƒ³ã‚¯ãƒ«ãƒ¼ãƒ‰ã™ã‚‹ãƒ˜ãƒƒãƒ€ãƒ•ァイルを `gdbm.h' ã‹ã‚‰ `hovel.h' ã«æ›ãˆã€ãƒ“ルドã®éš›ã®ãƒªãƒ³ã‚«ã‚ªãƒ—ションを `-lgdbm' ã‹ã‚‰ `-lqdbm' ã«æ›ãˆã‚‹ã ã‘ã§ã‚ˆã„。ãªãŠã€ã‚ªãƒªã‚¸ãƒŠãƒ«ã®GDBMã§ç”Ÿæˆã—ãŸãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルをHovelã§æ‰±ã†ã“ã¨ã¯ã§ããªã„。

Hovelを使ã†ãŸã‚ã«ã¯ã€`hovel.h' 㨠`stdlib.h' 㨠`sys/types.h' 㨠`sys/stat.h' をインクルードã™ã¹ãã§ã‚る。通常ã€ã‚½ãƒ¼ã‚¹ãƒ•ァイルã®å†’頭付近ã§ä»¥ä¸‹ã®è¨˜è¿°ã‚’行ã†ã€‚

#include <hovel.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>

Hovelã§ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’扱ã†éš›ã«ã¯ã€`GDBM_FILE' åž‹ã®ã‚ªãƒ–ジェクト(ãれ自体ãŒãƒã‚¤ãƒ³ã‚¿åž‹ï¼‰ã‚’ãƒãƒ³ãƒ‰ãƒ«ã¨ã—ã¦ç”¨ã„る。ãƒãƒ³ãƒ‰ãƒ«ã¯ã€é–¢æ•° `gdbm_open' ã§é–‹ãã€é–¢æ•° `gdbm_close' ã§é–‰ã˜ã‚‹ã€‚ãƒãƒ³ãƒ‰ãƒ«ã®ãƒ¡ãƒ³ãƒã‚’直接å‚ç…§ã™ã‚‹ã“ã¨ã¯æŽ¨å¥¨ã•れãªã„。Hovelã¯é€šå¸¸ã¯Depotã®ãƒ©ãƒƒãƒ‘ーã¨ã—ã¦å‹•作ã—ã¦ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルを扱ã†ãŒã€ãƒãƒ³ãƒ‰ãƒ«ã‚’é–‹ãéš›ã«é–¢æ•° `gdbm_open2' を用ã„ã‚‹ã“ã¨ã«ã‚ˆã£ã¦Curiaã®ãƒ©ãƒƒãƒ‘ーã¨ã—ã¦ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã‚’扱ã†ã‚ˆã†ã«ã™ã‚‹ã“ã¨ãŒã§ãる。

API

ãƒ‡ãƒ¼ã‚¿ã®æ ¼ç´ã€å‰Šé™¤ã€æ¤œç´¢ã«ç”¨ã„る関数ã¨ã®ãƒ‡ãƒ¼ã‚¿ã®æŽˆå—ã«ã¯ã€ã‚­ãƒ¼ã¨å€¤ã‚’表ç¾ã™ã‚‹ã®ã« `datum' åž‹ã®æ§‹é€ ä½“を用ã„る。

typedef struct { char *dptr; size_t dsize; } datum;
`dptr' ã¯ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã§ã‚る。`dsize' ã¯ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã®ã‚µã‚¤ã‚ºã§ã‚る。

外部変数 `gdbm_version' ã¯ãƒãƒ¼ã‚¸ãƒ§ãƒ³æƒ…å ±ã®æ–‡å­—列ã§ã‚る。

extern char *gdbm_version;
ã“ã®å¤‰æ•°ã®æŒ‡ã™é ˜åŸŸã¯æ›¸ãè¾¼ã¿ç¦æ­¢ã§ã‚る。

外部変数 `gdbm_errno' ã«ã¯ç›´å‰ã®ã‚¨ãƒ©ãƒ¼ã‚³ãƒ¼ãƒ‰ãŒè¨˜éŒ²ã•れる。エラーコードã®è©³ç´°ã«ã¤ã„ã¦ã¯ `hovel.h' ã‚’å‚ç…§ã™ã‚‹ã“ã¨ã€‚

extern gdbm_error gdbm_errno;
ã“ã®å¤‰æ•°ã®åˆæœŸå€¤ã¯ `GDBM_NO_ERROR' ã§ã‚る。ãã®ä»–ã®å€¤ã¨ã—ã¦ã€`GDBM_MALLOC_ERROR'ã€`GDBM_BLOCK_SIZE_ERROR'ã€`GDBM_FILE_OPEN_ERROR'ã€`GDBM_FILE_WRITE_ERROR'ã€`GDBM_FILE_SEEK_ERROR'ã€`GDBM_FILE_READ_ERROR'ã€`GDBM_BAD_MAGIC_NUMBER'ã€`GDBM_EMPTY_DATABASE'ã€`GDBM_CANT_BE_READER'ã€`GDBM_CANT_BE_WRITER'ã€`GDBM_READER_CANT_DELETE'ã€`GDBM_READER_CANT_STORE'ã€`GDBM_READER_CANT_REORGANIZE'ã€`GDBM_UNKNOWN_UPDATE'ã€`GDBM_ITEM_NOT_FOUND'ã€`GDBM_REORGANIZE_FAILED'ã€`GDBM_CANNOT_REPLACE'ã€`GDBM_ILLEGAL_DATA'ã€`GDBM_OPT_ALREADY_SET' ãŠã‚ˆã³ `GDBM_OPT_ILLEGAL' ãŒã‚る。

エラーコードã«å¯¾å¿œã™ã‚‹ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸æ–‡å­—列を得るã«ã¯ã€é–¢æ•° `gdbm_strerror' を用ã„る。

char *gdbm_strerror(gdbm_error gdbmerrno);
`gdbmerrno' ã¯ã‚¨ãƒ©ãƒ¼ã‚³ãƒ¼ãƒ‰ã‚’指定ã™ã‚‹ã€‚戻り値ã¯ã‚¨ãƒ©ãƒ¼ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã®æ–‡å­—列ã§ã‚りã€ãã®é ˜åŸŸã¯æ›¸ãè¾¼ã¿ç¦æ­¢é ˜åŸŸã§ã‚る。

GDBMæµã«ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®ãƒãƒ³ãƒ‰ãƒ«ã‚’作æˆã™ã‚‹ã«ã¯ã€é–¢æ•° `gdbm_open' を用ã„る。

GDBM_FILE gdbm_open(char *name, int block_size, int read_write, int mode, void (*fatal_func)(void));
`name' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®åå‰ã‚’指定ã™ã‚‹ã€‚`block_size' ã¯ç„¡è¦–ã•れる。`read_write' ã¯æŽ¥ç¶šãƒ¢ãƒ¼ãƒ‰ã‚’æŒ‡å®šã—ã€`GDBM_READER' ãªã‚‰ãƒªãƒ¼ãƒ€ã€`GDBM_WRITER' 㨠`GDBM_WRCREAT' 㨠`GDBM_NEWDB' ãªã‚‰ãƒ©ã‚¤ã‚¿ã¨ãªã‚‹ã€‚`GDBM_WRCREAT' ã®å ´åˆã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãŒå­˜åœ¨ã—ãªã‘れã°ä½œæˆã—ã€`GDBM_NEWDB' ã®å ´åˆã¯æ—¢ã«å­˜åœ¨ã—ã¦ã„ã¦ã‚‚æ–°ã—ã„データベースを作æˆã™ã‚‹ã€‚ライタã«å¯¾ã—ã¦ã¯ã€`GDBM_SYNC' ã‹ `GDBM_NOLOCK' ã‹ `GDBM_LOCKNB' ã‹ `GDBM_FAST' ã‹ `GDBM_SPARSE' ã¨ã®ãƒ“ット論ç†å’Œã«ã™ã‚‹ã“ã¨ãŒã§ãる。`GDBM_SYNC' ã¯å…¨ã¦ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹æ“作をディスクã¨åŒæœŸã•ã›ã€`GDBM_NOLOCK' ã¯ãƒ•ァイルロックを伴ã‚ãšã«ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’é–‹ãã€`GDBM_LOCKNB' ã¯ãƒ–ロックãªã—ã®ãƒ­ãƒƒã‚¯ã‚’行ã„ã€`GDBM_FAST' ã¯ç„¡è¦–ã•れる。`GDBM_SPARSE' ã¯QDBM独自ã®ã‚‚ã®ã§ã‚りã€ä½œæˆã™ã‚‹ãƒ•ァイルをスパースã«ã™ã‚‹ã€‚`mode' 㯠`open' ã‚³ãƒ¼ãƒ«ã«æ¸¡ã™ã‚‚ã®ã¨åŒã˜ã§ãƒ•ァイルã®ãƒ¢ãƒ¼ãƒ‰ã‚’指定ã™ã‚‹ã€‚`fatal_func' ã¯ç„¡è¦–ã•ã‚Œã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰ `NULL' ã§ã‚る。

QDBMæµã«ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®ãƒãƒ³ãƒ‰ãƒ«ã‚’作æˆã™ã‚‹ã«ã¯ã€é–¢æ•° `gdbm_open2' を用ã„る。

GDBM_FILE gdbm_open2(char *name, int read_write, int mode, int bnum, int dnum, int align);
`name' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®åå‰ã‚’指定ã™ã‚‹ã€‚`read_write' ã¯æŽ¥ç¶šãƒ¢ãƒ¼ãƒ‰ã‚’æŒ‡å®šã—ã€`GDBM_READER' ãªã‚‰ãƒªãƒ¼ãƒ€ã€`GDBM_WRITER' 㨠`GDBM_WRCREAT' 㨠`GDBM_NEWDB' ãªã‚‰ãƒ©ã‚¤ã‚¿ã¨ãªã‚‹ã€‚`GDBM_WRCREAT' ã®å ´åˆã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãŒå­˜åœ¨ã—ãªã‘れã°ä½œæˆã—ã€`GDBM_NEWDB' ã®å ´åˆã¯æ—¢ã«å­˜åœ¨ã—ã¦ã„ã¦ã‚‚æ–°ã—ã„データベースを作æˆã™ã‚‹ã€‚ライタã«å¯¾ã—ã¦ã¯ã€`GDBM_SYNC' ã‹ `GDBM_NOLOCK' ã‹ `GDBM_LOCKNB' ã‹ `GDBM_FAST' ã‹ `GDBM_SPARSE' ã¨ã®ãƒ“ット論ç†å’Œã«ã™ã‚‹ã“ã¨ãŒã§ãる。`GDBM_SYNC' ã¯å…¨ã¦ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹æ“作をディスクã¨åŒæœŸã•ã›ã€`GDBM_NOLOCK' ã¯ãƒ•ァイルロックを伴ã‚ãšã«ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’é–‹ãã€`GDBM_LOCKNB' ã¯ãƒ–ロックãªã—ã®ãƒ­ãƒƒã‚¯ã‚’行ã„ã€`GDBM_FAST' ã¯ç„¡è¦–ã•れる。`GDBM_SPARSE' ã¯QDBM独自ã®ã‚‚ã®ã§ã‚りã€ä½œæˆã™ã‚‹ãƒ•ァイルをスパースã«ã™ã‚‹ã€‚`mode' 㯠`open' コールもã—ã㯠`mkdir' ã‚³ãƒ¼ãƒ«ã«æ¸¡ã™ã‚‚ã®ã¨åŒã˜ã§ãƒ•ァイルやディレクトリã®ãƒ¢ãƒ¼ãƒ‰ã‚’指定ã™ã‚‹ã€‚`bnum' ã¯ãƒã‚±ãƒƒãƒˆé…列ã®è¦ç´ æ•°ã®ç›®å®‰ã‚’指定ã™ã‚‹ãŒã€0 以下ãªã‚‰ãƒ‡ãƒ•ォルト値ãŒä½¿ã‚れる。`dnum' ã¯è¦ç´ ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®æ•°ã‚’指定ã™ã‚‹ãŒã€0 以下ãªã‚‰è¿”ã•れるãƒãƒ³ãƒ‰ãƒ«ã¯Depotã®ãƒ©ãƒƒãƒ‘ーã¨ã—ã¦ç”Ÿæˆã•れã€ãã†ã§ãªã‘れã°Curiaã®ãƒ©ãƒƒãƒ‘ーã«ãªã‚‹ã€‚`align' ã¯ã‚¢ãƒ©ã‚¤ãƒ³ãƒ¡ãƒ³ãƒˆã®åŸºæœ¬ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰ `NULL' ã§ã‚る。既ã«ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãŒå­˜åœ¨ã™ã‚‹å ´åˆã€ãれãŒDepotã®ã‚‚ã®ã‹Curiaã®ã‚‚ã®ã‹ãŒè‡ªå‹•çš„ã«åˆ¤æ–­ã•れる。

データベースã¨ã®æŽ¥ç¶šã‚’é–‰ã˜ã¦ãƒãƒ³ãƒ‰ãƒ«ã‚’破棄ã™ã‚‹ã«ã¯ã€é–¢æ•° `gdbm_close' を用ã„る。

void gdbm_close(GDBM_FILE dbf);
`dbf' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚é–‰ã˜ãŸãƒãƒ³ãƒ‰ãƒ«ã®é ˜åŸŸã¯è§£æ”¾ã•れるã®ã§ã€ä»¥å¾Œã¯åˆ©ç”¨ã™ã‚‹ã“ã¨ãŒã§ããªããªã‚‹ã€‚

レコードを追加ã™ã‚‹ã«ã¯ã€é–¢æ•° `gdbm_store' を用ã„る。

int gdbm_store(GDBM_FILE dbf, datum key, datum content, int flag);
`dbf' ã¯ãƒ©ã‚¤ã‚¿ã§æŽ¥ç¶šã—ãŸãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`key' ã¯ã‚­ãƒ¼ã®æ§‹é€ ä½“を指定ã™ã‚‹ã€‚`content' ã¯å€¤ã®æ§‹é€ ä½“を指定ã™ã‚‹ã€‚`frags' ㌠`GDBM_INSERT' ãªã‚‰ã‚­ãƒ¼ã®é‡è¤‡æ™‚ã«æ›¸ãè¾¼ã¿ã‚’断念ã—ã€`GDBM_REPLACE' ãªã‚‰ä¸Šæ›¸ãを行ã†ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰ 0 ã€é‡è¤‡ã§ã®æ–­å¿µãªã‚‰ 1 ã€ãã®ä»–ã®ã‚¨ãƒ©ãƒ¼ãªã‚‰ -1 ã§ã‚る。

レコードを削除ã™ã‚‹ã«ã¯ã€é–¢æ•° `gdbm_delete' を用ã„る。

int gdbm_delete(GDBM_FILE dbf, datum key);
`dbf' ã¯ãƒ©ã‚¤ã‚¿ã§æŽ¥ç¶šã—ãŸãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`key' ã¯ã‚­ãƒ¼ã®æ§‹é€ ä½“を指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰ 0 ã€ã‚¨ãƒ©ãƒ¼ãªã‚‰ -1 ã§ã‚る。

レコードをå–å¾—ã™ã‚‹ã«ã¯ã€é–¢æ•° `gdbm_fetch' を用ã„る。

datum gdbm_fetch(GDBM_FILE dbf, datum key);
`dbf' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`key' ã¯ã‚­ãƒ¼ã®æ§‹é€ ä½“を指定ã™ã‚‹ã€‚戻り値ã¯å€¤ã®æ§‹é€ ä½“ã§ã‚る。該当ãŒã‚れã°ãƒ¡ãƒ³ãƒ `dptr' ãŒãã®é ˜åŸŸã‚’指ã—ã€`dsize' ãŒãã®ã‚µã‚¤ã‚ºã‚’示ã™ã€‚該当ãŒãªã‘れ㰠`dptr' ã®å€¤ã¯ `NULL' ã¨ãªã‚‹ã€‚戻り値ã®ãƒ¡ãƒ³ãƒ `dptr' ã®æŒ‡ã™é ˜åŸŸã¯ `malloc' ã§ç¢ºä¿ã•れるã®ã§ã€ä¸è¦ã«ãªã£ãŸã‚‰ `free' ã§è§£æ”¾ã™ã‚‹ã¹ãã§ã‚る。

レコードãŒå­˜åœ¨ã™ã‚‹ã‹èª¿ã¹ã‚‹ã«ã¯ã€é–¢æ•° `gdbm_exists' を用ã„る。

int gdbm_exists(GDBM_FILE dbf, datum key);
`dbf' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`key' ã¯ã‚­ãƒ¼ã®æ§‹é€ ä½“を指定ã™ã‚‹ã€‚戻り値ã¯è©²å½“ãŒã‚れã°çœŸã§ã‚りã€è©²å½“ãŒãªã„å ´åˆã‚„エラーã®å ´åˆã¯å½ã§ã‚る。

最åˆã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã®ã‚­ãƒ¼ã‚’å¾—ã‚‹ã«ã¯ã€é–¢æ•° `gdbm_firstkey' を用ã„る。

datum gdbm_firstkey(GDBM_FILE dbf);
`dbf' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚戻り値ã¯ã‚­ãƒ¼ã®æ§‹é€ ä½“ã§ã‚る。該当ãŒã‚れã°ãƒ¡ãƒ³ãƒ `dptr' ãŒãã®é ˜åŸŸã‚’指ã—ã€`dsize' ãŒãã®ã‚µã‚¤ã‚ºã‚’示ã™ã€‚該当ãŒãªã‘れ㰠`dptr' ã®å€¤ã¯ `NULL' ã¨ãªã‚‹ã€‚戻り値ã®ãƒ¡ãƒ³ãƒ `dptr' ã®æŒ‡ã™é ˜åŸŸã¯ `malloc' ã§ç¢ºä¿ã•れるã®ã§ã€ä¸è¦ã«ãªã£ãŸã‚‰ `free' ã§è§£æ”¾ã™ã‚‹ã¹ãã§ã‚る。

次ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã®ã‚­ãƒ¼ã‚’å¾—ã‚‹ã«ã¯ã€é–¢æ•° gdbm_nextkey を用ã„る。

datum gdbm_nextkey(GDBM_FILE dbf, datum key);
`dbf' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`key' ã¯ç„¡è¦–ã•れる。戻り値ã¯ã‚­ãƒ¼ã®æ§‹é€ ä½“ã§ã‚る。該当ãŒã‚れã°ãƒ¡ãƒ³ãƒ `dptr' ãŒãã®é ˜åŸŸã‚’指ã—ã€`dsize' ãŒãã®ã‚µã‚¤ã‚ºã‚’示ã™ã€‚該当ãŒãªã‘れ㰠`dptr' ã®å€¤ã¯ `NULL' ã¨ãªã‚‹ã€‚戻り値ã®ãƒ¡ãƒ³ãƒ `dptr' ã®æŒ‡ã™é ˜åŸŸã¯ `malloc' ã§ç¢ºä¿ã•れるã®ã§ã€ä¸è¦ã«ãªã£ãŸã‚‰ `free' ã§è§£æ”¾ã™ã‚‹ã¹ãã§ã‚る。

データベースを更新ã—ãŸå†…容をファイルã¨ãƒ‡ãƒã‚¤ã‚¹ã«åŒæœŸã•ã›ã‚‹ã«ã¯ã€é–¢æ•° `gdbm_sync' を用ã„る。

void gdbm_sync(GDBM_FILE dbf);
`dbf' ã¯ãƒ©ã‚¤ã‚¿ã§æŽ¥ç¶šã—ãŸãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚

データベースを最é©åŒ–ã™ã‚‹ã«ã¯ã€é–¢æ•° `gdbm_reorganize' を用ã„る。

int gdbm_reorganize(GDBM_FILE dbf);
`dbf' ã¯ãƒ©ã‚¤ã‚¿ã§æŽ¥ç¶šã—ãŸãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰ 0 ã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰ -1 ã§ã‚る。

データベースファイルã®ãƒ•ァイルディスクリプタを得るã«ã¯ã€é–¢æ•° `gdbm_fdesc' を用ã„る。

int gdbm_fdesc(GDBM_FILE dbf);
`dbf' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚戻り値ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルã®ãƒ•ァイルディスクリプタã§ã‚る。データベースãŒãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªãªã‚‰ã€æˆ»ã‚Šå€¤ã¯ -1 ã§ã‚る。

関数 `gdbm_setopt' ã¯ä½•ã‚‚ã—ãªã„。

int gdbm_setopt(GDBM_FILE dbf, int option, int *value, int size);
`dbf' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`option' ã¯ç„¡è¦–ã•れる。`value' ã¯ç„¡è¦–ã•れる。`size' ã¯ç„¡è¦–ã•れる。戻り値㯠0 ã§ã‚る。ã“ã®é–¢æ•°ã¯äº’æ›æ€§ã®ãŸã‚ã«ã®ã¿å­˜åœ¨ã™ã‚‹ã€‚

サンプルコード

åå‰ã¨å¯¾å¿œã•ã›ã¦é›»è©±ç•ªå·ã‚’æ ¼ç´ã—ã€ãれを検索ã™ã‚‹ã‚¢ãƒ—リケーションã®ã‚µãƒ³ãƒ—ルコードを以下ã«ç¤ºã™ã€‚

#include <hovel.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <string.h>

#define NAME     "mikio"
#define NUMBER   "000-1234-5678"
#define DBNAME   "book"

int main(int argc, char **argv){
  GDBM_FILE dbf;
  datum key, val;
  int i;

  /* データベースを開ã */
  if(!(dbf = gdbm_open(DBNAME, 0, GDBM_WRCREAT, 00644, NULL))){
    fprintf(stderr, "gdbm_open: %s\n", gdbm_strerror(gdbm_errno));
    return 1;
  }

  /* レコードを準備ã™ã‚‹ */
  key.dptr = NAME;
  key.dsize = strlen(NAME);
  val.dptr = NUMBER;
  val.dsize = strlen(NUMBER);

  /* レコードを格ç´ã™ã‚‹ */
  if(gdbm_store(dbf, key, val, GDBM_REPLACE) != 0){
    fprintf(stderr, "gdbm_store: %s\n", gdbm_strerror(gdbm_errno));
  }

  /* レコードを検索ã™ã‚‹ */
  val = gdbm_fetch(dbf, key);
  if(val.dptr){
    printf("Name: %s\n", NAME);
    printf("Number: ");
    for(i = 0; i < val.dsize; i++){
      putchar(val.dptr[i]);
    }
    putchar('\n');
    free(val.dptr);
  } else {
    fprintf(stderr, "gdbm_fetch: %s\n", gdbm_strerror(gdbm_errno));
  }

  /* データベースを閉ã˜ã‚‹ */
  gdbm_close(dbf);

  return 0;
}

注記

Hovelを利用ã—ãŸãƒ—ログラムをビルドã™ã‚‹æ–¹æ³•ã¯ã€Depotã®å ´åˆã¨å…¨ãåŒã˜ã§ã‚ã‚‹ã€‚ãƒªãƒ³ã‚«ã«æ¸¡ã™ã‚ªãƒ—ション㯠`-lgdbm' ã§ã¯ãªã `-lqdbm' ã§ã‚る。

gcc -I/usr/local/include -o sample sample.c -L/usr/local/lib -lqdbm

POSIXスレッドを有効ã«ã—ã¦QDBMをビルドã—ãŸå ´åˆã€å¤–部変数 `gdbm_errno' ã¯ã‚¹ãƒ¬ãƒƒãƒ‰å›ºæœ‰ãƒ‡ãƒ¼ã‚¿ã¸ã®å‚ç…§ã¨ã—ã¦æ‰±ã‚れã€Hovelã®å„関数ã¯ãƒªã‚¨ãƒ³ãƒˆãƒ©ãƒ³ãƒˆã«ãªã‚‹ã€‚ãã®å ´åˆã€ã‚¹ãƒ¬ãƒƒãƒ‰é–“ã§åŒæ™‚ã«åŒã˜ãƒãƒ³ãƒ‰ãƒ«ã«ã‚¢ã‚¯ã‚»ã‚¹ã—ãªã„é™ã‚Šã¯ã€å„関数ã¯ã‚¹ãƒ¬ãƒƒãƒ‰ã‚»ãƒ¼ãƒ•ã§ã‚る。ãŸã ã—ã€`errno' ã‚„ `malloc' ç­‰ãŒã‚¹ãƒ¬ãƒƒãƒ‰ã‚»ãƒ¼ãƒ•ãªå‡¦ç†ç³»ã§ã‚ã‚‹ã“ã¨ãŒå‰æã¨ãªã‚‹ã€‚


Hovel用コマンド

Hovelã«å¯¾å¿œã™ã‚‹ã‚³ãƒžãƒ³ãƒ‰ãƒ©ã‚¤ãƒ³ã‚¤ãƒ³ã‚¿ãƒ•ェースã¯ä»¥ä¸‹ã®ã‚‚ã®ã§ã‚る。

コマンド `hvmgr' ã¯Hovelã‚„ãã®ã‚¢ãƒ—リケーションã®ãƒ‡ãƒãƒƒã‚°ã«å½¹ç«‹ã¤ãƒ„ールã§ã‚る。データベースを更新ã—ãŸã‚Šã€ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®çŠ¶æ…‹ã‚’èª¿ã¹ãŸã‚Šã™æ©Ÿèƒ½ã‚’æŒã¤ã€‚シェルスクリプトã§ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚¢ãƒ—リケーションを作るã®ã«ã‚‚利用ã§ãã‚‹ã€‚ä»¥ä¸‹ã®æ›¸å¼ã§ç”¨ã„る。`name' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹åã€`key' ã¯ãƒ¬ã‚³ãƒ¼ãƒ‰ã®ã‚­ãƒ¼ã€`val' ã¯ãƒ¬ã‚³ãƒ¼ãƒ‰ã®å€¤ã‚’指定ã™ã‚‹ã€‚

hvmgr [-qdbm bnum dnum] [-s] create name
データベースファイルを作æˆã™ã‚‹ã€‚
hvmgr store [-qdbm] [-kx] [-vx|-vf] [-insert] name key val
キーã¨å€¤ã«å¯¾å¿œã™ã‚‹ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’追加ã™ã‚‹ã€‚
hvmgr delete [-qdbm] [-kx] name key
キーã«å¯¾å¿œã™ã‚‹ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’削除ã™ã‚‹ã€‚
hvmgr fetch [-qdbm] [-kx] [-ox] [-n] name key
キーã«å¯¾å¿œã™ã‚‹ãƒ¬ã‚³ãƒ¼ãƒ‰ã®å€¤ã‚’å–å¾—ã—ã¦æ¨™æº–出力ã™ã‚‹ã€‚
hvmgr list [-qdbm] [-ox] name
データベース内ã®å…¨ã¦ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã®ã‚­ãƒ¼ã¨å€¤ã‚’ã‚¿ãƒ–ã¨æ”¹è¡Œã§åŒºåˆ‡ã£ã¦æ¨™æº–出力ã™ã‚‹ã€‚
hvmgr optimize [-qdbm] name
データベースを最é©åŒ–ã™ã‚‹ã€‚

å„オプションã¯ä»¥ä¸‹ã®æ©Ÿèƒ½ã‚’æŒã¤ã€‚

  • -qdbm [bnum dnum] : `gdbm_open2' ã§ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’é–‹ã。`bnum' 㨠`dnum' ã¯ãƒã‚±ãƒƒãƒˆé…列ã®è¦ç´ æ•°ã¨ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®åˆ†å‰²æ•°ã‚’指定ã™ã‚‹ã€‚
  • -s : ファイルをスパースã«ã™ã‚‹ã€‚
  • -kx : 2æ¡å˜ä½ã®16進数ã«ã‚ˆã‚‹ãƒã‚¤ãƒŠãƒªè¡¨ç¾ã¨ã—㦠`key' を扱ã†ã€‚
  • -vx : 2æ¡å˜ä½ã®16進数ã«ã‚ˆã‚‹ãƒã‚¤ãƒŠãƒªè¡¨ç¾ã¨ã—㦠`val' を扱ã†ã€‚
  • -vf : åå‰ãŒ `val' ã®ãƒ•ァイルã®ãƒ‡ãƒ¼ã‚¿ã‚’値ã¨ã—ã¦èª­ã¿è¾¼ã‚€ã€‚
  • -insert : 既存ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã¨ã‚­ãƒ¼ãŒé‡è¤‡æ™‚ã«ä¸Šæ›¸ãã›ãšã«ã‚¨ãƒ©ãƒ¼ã«ã™ã‚‹ã€‚
  • -ox : 2æ¡å˜ä½ã®16進数ã«ã‚ˆã‚‹ãƒã‚¤ãƒŠãƒªè¡¨ç¾ã¨ã—ã¦æ¨™æº–出力を行ã†ã€‚
  • -n : æ¨™æº–å‡ºåŠ›ã®æœ«å°¾ã«ä»˜åŠ ã•れる改行文字ã®å‡ºåŠ›ã‚’æŠ‘åˆ¶ã™ã‚‹ã€‚

ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯å‡¦ç†ãŒæ­£å¸¸ã«çµ‚了ã™ã‚Œã° 0 ã‚’è¿”ã—ã€ã‚¨ãƒ©ãƒ¼ãŒã‚れã°ãれ以外ã®å€¤ã‚’è¿”ã—ã¦çµ‚了ã™ã‚‹ã€‚

コマンド `hvtest' ã¯Hovelã®æ©Ÿèƒ½ãƒ†ã‚¹ãƒˆã‚„性能テストã«ç”¨ã„るツールã§ã‚る。ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã«ã‚ˆã£ã¦ç”Ÿæˆã•れãŸãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルを `hvmgr' ã«ã‚ˆã£ã¦è§£æžã—ãŸã‚Šã€`time' コマンドã«ã‚ˆã£ã¦ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã®å®Ÿè¡Œæ™‚間を計ã£ãŸã‚Šã™ã‚‹ã¨ã‚ˆã„ã€‚ä»¥ä¸‹ã®æ›¸å¼ã§ç”¨ã„る。`name' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹åã€`rnum' ã¯ãƒ¬ã‚³ãƒ¼ãƒ‰æ•°ã‚’指定ã™ã‚‹ã€‚

hvtest write [-qdbm] [-s] name rnum
`00000001'ã€`00000002' ã®ã‚ˆã†ã«å¤‰åŒ–ã™ã‚‹8ãƒã‚¤ãƒˆã®ã‚­ãƒ¼ã¨é©å½“ãª8ãƒã‚¤ãƒˆã®å€¤ã‚’連続ã—ã¦ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«è¿½åŠ ã™ã‚‹ã€‚
hvtest read [-qdbm] name rnum
上記ã§ç”Ÿæˆã—ãŸãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’検索ã™ã‚‹ã€‚

å„オプションã¯ä»¥ä¸‹ã®æ©Ÿèƒ½ã‚’æŒã¤ã€‚

  • -qdbm : `gdbm_open2' を用ã„ã¦Curiaã®ãƒãƒ³ãƒ‰ãƒ«ã‚’é–‹ã。
  • -s : ファイルをスパースã«ã™ã‚‹ã€‚

ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯å‡¦ç†ãŒæ­£å¸¸ã«çµ‚了ã™ã‚Œã° 0 ã‚’è¿”ã—ã€ã‚¨ãƒ©ãƒ¼ãŒã‚れã°ãれ以外ã®å€¤ã‚’è¿”ã—ã¦çµ‚了ã™ã‚‹ã€‚


Cabin: ユーティリティAPI

概è¦

Cabinã¯ãƒ¡ãƒ¢ãƒªä¸Šã§ç°¡å˜ã«ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’扱ã†ãŸã‚ã®ãƒ¡ãƒ¢ãƒªç¢ºä¿é–¢æ•°ã‚„整列関数や拡張å¯èƒ½ãªãƒ‡ãƒ¼ã‚¿ã‚„é…列リストやãƒãƒƒã‚·ãƒ¥ãƒžãƒƒãƒ—やヒープé…列ãªã©æä¾›ã™ã‚‹ãƒ¦ãƒ¼ãƒ†ã‚£ãƒªãƒ†ã‚£ã®APIã§ã‚る。MIMEã‚„CSVã‚„XMLã‚’è§£æžã™ã‚‹æ©Ÿèƒ½ã‚„ã€å„種ã®ç¬¦å·åŒ–ã¨å¾©å·ã‚’è¡Œã†æ©Ÿèƒ½ã‚‚å‚™ãˆã‚‹ã€‚

Cabinを使ã†ãŸã‚ã«ã¯ã€`cabin.h' 㨠`stdlib.h' をインクルードã™ã¹ãã§ã‚る。通常ã€ã‚½ãƒ¼ã‚¹ãƒ•ァイルã®å†’頭付近ã§ä»¥ä¸‹ã®è¨˜è¿°ã‚’行ã†ã€‚

#include <cabin.h>
#include <stdlib.h>

æ‹¡å¼µå¯èƒ½ãªãƒ‡ãƒ¼ã‚¿ã‚’扱ã†éš›ã«ã¯ã€`CBDATUM' åž‹ã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’ãƒãƒ³ãƒ‰ãƒ«ã¨ã—ã¦ç”¨ã„る。データãƒãƒ³ãƒ‰ãƒ«ã¯ã€é–¢æ•° `cbdatumopen' ã§é–‹ãã€é–¢æ•° `cbdatumclose' ã§é–‰ã˜ã‚‹ã€‚リストを扱ã†éš›ã«ã¯ã€`CBLIST' åž‹ã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’ãƒãƒ³ãƒ‰ãƒ«ã¨ã—ã¦ç”¨ã„る。リストãƒãƒ³ãƒ‰ãƒ«ã¯ã€é–¢æ•° `cblistopen' ã§é–‹ãã€é–¢æ•° `cblistclose' ã§é–‰ã˜ã‚‹ã€‚マップを扱ã†éš›ã«ã¯ã€`CBMAP' åž‹ã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’ãƒãƒ³ãƒ‰ãƒ«ã¨ã—ã¦ç”¨ã„る。マップãƒãƒ³ãƒ‰ãƒ«ã¯ã€é–¢æ•° `cbmapopen' ã§é–‹ãã€é–¢æ•° `cbmapclose' ã§é–‰ã˜ã‚‹ã€‚ヒープé…列を扱ã†éš›ã«ã¯ `CBHEAP' åž‹ã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’ãƒãƒ³ãƒ‰ãƒ«ã¨ã—ã¦ç”¨ã„る。ヒープãƒãƒ³ãƒ‰ãƒ«ã¯é–¢æ•° `cbheapopen' ã§é–‹ãã€é–¢æ•° `cbheapclose' ã§é–‰ã˜ã‚‹ã€‚å„ãƒãƒ³ãƒ‰ãƒ«ã®ãƒ¡ãƒ³ãƒã‚’直接å‚ç…§ã™ã‚‹ã“ã¨ã¯æŽ¨å¥¨ã•れãªã„。

API

外部変数 `cbfatalfunc' ã¯è‡´å‘½çš„エラーをãƒãƒ³ãƒ‰ãƒªãƒ³ã‚°ã™ã‚‹ã‚³ãƒ¼ãƒ«ãƒãƒƒã‚¯é–¢æ•°ã§ã‚る。

extern void (*cbfatalfunc)(const char *message);
引数ã¯ã‚¨ãƒ©ãƒ¼ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚’指定ã™ã‚‹ã€‚ã“ã®å¤‰æ•°ã®åˆæœŸå€¤ã¯ `NULL' ã§ã‚りã€`NULL' ãªã‚‰ã°è‡´å‘½çš„エラーã®ç™ºç”Ÿæ™‚ã«ã¯ãƒ‡ãƒ•ォルトã®é–¢æ•°ãŒå‘¼ã°ã‚Œã‚‹ã€‚致命的エラーã¯ãƒ¡ãƒ¢ãƒªã®å‰²ã‚Šå½“ã¦ã«å¤±æ•—ã—ãŸéš›ã«èµ·ã“る。

メモリ上ã«é ˜åŸŸã‚’確ä¿ã™ã‚‹ã«ã¯ã€é–¢æ•° `cbmalloc' を用ã„る。

void *cbmalloc(size_t size);
`size' ã¯é ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã€‚戻り値ã¯ç¢ºä¿ã—ãŸé ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã§ã‚る。戻り値ã®é ˜åŸŸã¯ `malloc' ã§ç¢ºä¿ã•れるã®ã§ã€ä¸è¦ã«ãªã£ãŸã‚‰ `free' ã§è§£æ”¾ã™ã‚‹ã¹ãã§ã‚る。

メモリ上ã®é ˜åŸŸã‚’å†ç¢ºä¿ã™ã‚‹ã«ã¯ã€é–¢æ•° `cbrealloc' を用ã„る。

void *cbrealloc(void *ptr, size_t size);
`ptr' ã¯é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`size' ã¯é ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã€‚戻り値ã¯å†ç¢ºä¿ã—ãŸé ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã§ã‚る。戻り値ã®é ˜åŸŸã¯ `remalloc' ã§ç¢ºä¿ã•れるã®ã§ã€ä¸è¦ã«ãªã£ãŸã‚‰ `free' ã§è§£æ”¾ã™ã‚‹ã¹ãã§ã‚る。

メモリ上ã®é ˜åŸŸã‚’複製ã™ã‚‹ã«ã¯ã€é–¢æ•° `cbmemdup' を用ã„る。

char *cbmemdup(const char *ptr, int size);
`ptr' ã¯é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`size' ã¯é ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã€‚戻り値ã¯å†ç¢ºä¿ã—ãŸé ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã§ã‚る。戻り値ã¯è¤‡è£½ã®é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã§ã‚る。戻り値ã®é ˜åŸŸã¯ã€å®Ÿéš›ã«ã¯1ãƒã‚¤ãƒˆå¤šã確ä¿ã—ã¦çµ‚端文字ãŒç½®ã‹ã‚Œã‚‹ã®ã§ã€æ–‡å­—列ã¨ã—ã¦åˆ©ç”¨ã§ãる。戻り値ã®é ˜åŸŸã¯ `malloc' ã§ç¢ºä¿ã•れるã®ã§ã€ä¸è¦ã«ãªã£ãŸã‚‰ `free' ã§è§£æ”¾ã™ã‚‹ã¹ãã§ã‚る。

メモリ上ã®é–‹æ”¾ã‚’解放ã™ã‚‹ã«ã¯ã€é–¢æ•° `cbfree' を用ã„る。

void cbfree(void *ptr);
`ptr' ã¯é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ãŒã€`NULL' ã®å ´åˆã¯ä½•ã‚‚ã—ãªã„。ã“ã®é–¢æ•°ã¯ `free' ã®ãƒ©ãƒƒãƒ‘ーã«éŽãŽãªã„ãŒã€`malloc' シリーズã®åˆ¥ã®ãƒ‘ッケージを使ã†ã‚¢ãƒ—リケーションã«ãŠã„ã¦QDBMãŒç¢ºä¿ã—ãŸé ˜åŸŸã‚’解放ã™ã‚‹ã®ã«ä¾¿åˆ©ã§ã‚る。

オブジェクトã®ãƒã‚¤ãƒ³ã‚¿ã‹ãƒãƒ³ãƒ‰ãƒ«ã‚’グローãƒãƒ«ã‚¬ãƒ™ãƒ¼ã‚¸ã‚³ãƒ¬ã‚¯ã‚¿ã«ç™»éŒ²ã™ã‚‹ã«ã¯ã€é–¢æ•° `cbglobalgc' を用ã„る。

void cbglobalgc(void *ptr, void (*func)(void *));
`ptr' ã¯ã‚ªãƒ–ジェクトã®ãƒã‚¤ãƒ³ã‚¿ã‹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`func' ã¯ã‚ªãƒ–ジェクトã®ãƒªã‚½ãƒ¼ã‚¹ã‚’解放ã™ã‚‹é–¢æ•°ã‚’指定ã™ã‚‹ã€‚ãã®å¼•æ•°ã¯è§£æ”¾ã™ã‚‹ã‚ªãƒ–ジェクトã®ãƒã‚¤ãƒ³ã‚¿ã‹ãƒãƒ³ãƒ‰ãƒ«ã§ã‚る。ã“ã®é–¢æ•°ã¯ã€`main' 関数ãŒãƒªã‚¿ãƒ¼ãƒ³ã™ã‚‹ã‹ `exit' 関数ãŒå‘¼ã°ã‚Œã¦ãƒ—ãƒ­ã‚»ã‚¹ãŒæ­£å¸¸çµ‚了ã™ã‚‹éš›ã«ã€ã‚ªãƒ–ジェクトã®ãƒªã‚½ãƒ¼ã‚¹ãŒè§£æ”¾ã•れるã“ã¨ã‚’ä¿è¨¼ã™ã‚‹ã€‚

グローãƒãƒ«ã‚¬ãƒ™ãƒ¼ã‚¸ã‚³ãƒ¬ã‚¯ã‚¿ã‚’明示的ã«ç™ºå‹•ã•ã›ã‚‹ã«ã¯ã€é–¢æ•° `cbggcsweep' を用ã„る。

void cbggcsweep(void);
ã“ã®é–¢æ•°ã‚’呼んã å¾Œã¯ã‚°ãƒ­ãƒ¼ãƒãƒ«ã‚¬ãƒ™ãƒ¼ã‚¸ã‚³ãƒ¬ã‚¯ã‚¿ã«ç™»éŒ²ã—ã¦ã‚ã£ãŸã‚ªãƒ–ジェクトã¯åˆ©ç”¨ã™ã‚‹ã“ã¨ãŒã§ããªããªã‚‹ã“ã¨ã«æ³¨æ„ã™ã‚‹ã“ã¨ã€‚グローãƒãƒ«ã‚¬ãƒ™ãƒ¼ã‚¸ã‚³ãƒ¬ã‚¯ã‚¿ã¯åˆæœŸåŒ–ã•れるã®ã§ã€æ–°ã—ã„オブジェクトを入れるã“ã¨ãŒã§ãるよã†ã«ãªã‚‹ã€‚

仮想メモリã®å‰²ã‚Šå½“ã¦å¯èƒ½æ€§ã‚’調ã¹ã‚‹ã«ã¯ã€é–¢æ•° `cbvmemavail' を用ã„る。

int cbvmemavail(size_t size);
`size' ã¯æ–°ãŸã«å‰²ã‚Šå½“ã¦å¯èƒ½ã§ã‚ã‚‹ã¹ã領域ã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã€‚戻り値ã¯å‰²ã‚Šå½“ã¦ãŒå¯èƒ½ã§ã‚れã°çœŸã€ãã†ã§ãªã‘れã°å½ã§ã‚る。

é…列ã®å„è¦ç´ ã‚’æŒ¿å…¥ã‚½ãƒ¼ãƒˆã§æ•´åˆ—ã•ã›ã‚‹ã«ã¯ã€é–¢æ•° `cbisort' を用ã„る。

void cbisort(void *base, int nmemb, int size, int(*compar)(const void *, const void *));
`base' ã¯é…列ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`nmemb' ã¯é…列ã®è¦ç´ æ•°ã‚’指定ã™ã‚‹ã€‚`size' ã¯å„è¦ç´ ã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã€‚`compar' ã¯æ¯”較関数を指定ã™ã‚‹ã€‚二ã¤ã®å¼•æ•°ã¯è¦ç´ ã¸ã®ãƒã‚¤ãƒ³ã‚¿ã§ã‚る。比較関数ã¯å‰è€…ãŒå¤§ãã‘ã‚Œã°æ­£æ•°ã‚’ã€å¾Œè€…ãŒå¤§ãã‘れã°è² æ•°ã‚’ã€ä¸¡è€…ãŒç­‰ã—ã‘れ㰠0 ã‚’è¿”ã™ã¹ãã§ã‚る。挿入ソートã¯ã€ã»ã¨ã‚“ã©ã®è¦ç´ ãŒæ—¢ã«æ•´åˆ—済ã¿ã®å ´åˆã«ã®ã¿æœ‰ç”¨ã§ã‚る。

é…列ã®å„è¦ç´ ã‚’ã‚·ã‚§ãƒ«ã‚½ãƒ¼ãƒˆã§æ•´åˆ—ã•ã›ã‚‹ã«ã¯ã€é–¢æ•° `cbssort' を用ã„る。

void cbssort(void *base, int nmemb, int size, int(*compar)(const void *, const void *));
`base' ã¯é…列ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`nmemb' ã¯é…列ã®è¦ç´ æ•°ã‚’指定ã™ã‚‹ã€‚`size' ã¯å„è¦ç´ ã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã€‚`compar' ã¯æ¯”較関数を指定ã™ã‚‹ã€‚二ã¤ã®å¼•æ•°ã¯è¦ç´ ã¸ã®ãƒã‚¤ãƒ³ã‚¿ã§ã‚る。比較関数ã¯å‰è€…ãŒå¤§ãã‘ã‚Œã°æ­£æ•°ã‚’ã€å¾Œè€…ãŒå¤§ãã‘れã°è² æ•°ã‚’ã€ä¸¡è€…ãŒç­‰ã—ã‘れ㰠0 ã‚’è¿”ã™ã¹ãã§ã‚る。ã»ã¨ã‚“ã©ã®è¦ç´ ãŒæ•´åˆ—済ã¿ã®å ´åˆã€ã‚·ã‚§ãƒ«ã‚½ãƒ¼ãƒˆã®æ–¹ãŒãƒ’ープソートやクイックソートより速ã„ã‹ã‚‚ã—れãªã„。

é…列ã®å„è¦ç´ ã‚’ãƒ’ãƒ¼ãƒ—ã‚½ãƒ¼ãƒˆã§æ•´åˆ—ã•ã›ã‚‹ã«ã¯ã€é–¢æ•° `cbhsort' を用ã„る。

void cbhsort(void *base, int nmemb, int size, int(*compar)(const void *, const void *));
`base' ã¯é…列ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`nmemb' ã¯é…列ã®è¦ç´ æ•°ã‚’指定ã™ã‚‹ã€‚`size' ã¯å„è¦ç´ ã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã€‚`compar' ã¯æ¯”較関数を指定ã™ã‚‹ã€‚二ã¤ã®å¼•æ•°ã¯è¦ç´ ã¸ã®ãƒã‚¤ãƒ³ã‚¿ã§ã‚る。比較関数ã¯å‰è€…ãŒå¤§ãã‘ã‚Œã°æ­£æ•°ã‚’ã€å¾Œè€…ãŒå¤§ãã‘れã°è² æ•°ã‚’ã€ä¸¡è€…ãŒç­‰ã—ã‘れ㰠0 ã‚’è¿”ã™ã¹ãã§ã‚る。ヒープソートã¯å…¥åŠ›ã®åりã«å¯¾ã—ã¦é ‘丈ã§ã‚ã‚‹ãŒã€ã»ã¨ã‚“ã©ã®å ´åˆã§ã‚¯ã‚¤ãƒƒã‚¯ã‚½ãƒ¼ãƒˆã®æ–¹ãŒé€Ÿã„。

é…列ã®å„è¦ç´ ã‚’ã‚¯ã‚¤ãƒƒã‚¯ã‚½ãƒ¼ãƒˆã§æ•´åˆ—ã•ã›ã‚‹ã«ã¯ã€é–¢æ•° `cbqsort' を用ã„る。

void cbqsort(void *base, int nmemb, int size, int(*compar)(const void *, const void *));
`base' ã¯é…列ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`nmemb' ã¯é…列ã®è¦ç´ æ•°ã‚’指定ã™ã‚‹ã€‚`size' ã¯å„è¦ç´ ã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã€‚`compar' ã¯æ¯”較関数を指定ã™ã‚‹ã€‚二ã¤ã®å¼•æ•°ã¯è¦ç´ ã¸ã®ãƒã‚¤ãƒ³ã‚¿ã§ã‚る。比較関数ã¯å‰è€…ãŒå¤§ãã‘ã‚Œã°æ­£æ•°ã‚’ã€å¾Œè€…ãŒå¤§ãã‘れã°è² æ•°ã‚’ã€ä¸¡è€…ãŒç­‰ã—ã‘れ㰠0 ã‚’è¿”ã™ã¹ãã§ã‚る。入力ã®åã‚Šã«æ•感ã§ã¯ã‚ã‚‹ãŒã€ã‚¯ã‚¤ãƒƒã‚¯ã‚½ãƒ¼ãƒˆã¯æœ€é€Ÿã®æ•´åˆ—アルゴリズムã§ã‚る。

大文字ã¨å°æ–‡å­—ã®é•ã„を無視ã—ã¦äºŒã¤ã®æ–‡å­—列を比較ã™ã‚‹ã«ã¯ã€é–¢æ•° `cbstricmp' を用ã„る。

int cbstricmp(const char *astr, const char *bstr);
`astr' ã¯ä¸€æ–¹ã®æ–‡å­—列ã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`bstr' ã¯ä»–æ–¹ã®æ–‡å­—列ã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚戻り値ã¯å‰è€…ãŒå¤§ãã‘ã‚Œã°æ­£ã€å¾Œè€…ãŒå¤§ãã‘れã°è² ã€ä¸¡è€…ãŒç­‰ä¾¡ãªã‚‰ 0 ã§ã‚る。ASCIIコード中ã®ã‚¢ãƒ«ãƒ•ァベットã®å¤§æ–‡å­—ã¨å°æ–‡å­—ã¯åŒºåˆ¥ã•れãªã„。

文字列ãŒã‚るキーã§å§‹ã¾ã£ã¦ã„ã‚‹ã‹èª¿ã¹ã‚‹ã«ã¯ã€é–¢æ•° `cbstrfwmatch' を用ã„る。

int cbstrfwmatch(const char *str, const char *key);
`str' ã¯å¯¾è±¡ã®æ–‡å­—列ã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`key' ã¯å‰æ–¹ä¸€è‡´ã®ã‚­ãƒ¼ã®æ–‡å­—列ã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚戻り値ã¯å¯¾è±¡ã®æ–‡å­—列ãŒã‚­ãƒ¼ã§å§‹ã¾ã£ã¦ã„れã°çœŸã€ãã†ã§ãªã‘れã°å½ã§ã‚る。

大文字ã¨å°æ–‡å­—ã®é•ã„を無視ã—ã¤ã¤ã€æ–‡å­—列ãŒã‚るキーã§å§‹ã¾ã£ã¦ã„ã‚‹ã‹èª¿ã¹ã‚‹ã«ã¯ã€é–¢æ•° `cbstrfwimatch' を用ã„る。

int cbstrfwimatch(const char *str, const char *key);
`str' ã¯å¯¾è±¡ã®æ–‡å­—列ã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`key' ã¯å‰æ–¹ä¸€è‡´ã®ã‚­ãƒ¼ã®æ–‡å­—列ã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚戻り値ã¯å¯¾è±¡ã®æ–‡å­—列ãŒã‚­ãƒ¼ã§å§‹ã¾ã£ã¦ã„れã°çœŸã€ãã†ã§ãªã‘れã°å½ã§ã‚る。ASCIIコード中ã®ã‚¢ãƒ«ãƒ•ァベットã®å¤§æ–‡å­—ã¨å°æ–‡å­—ã¯åŒºåˆ¥ã•れãªã„。

文字列ãŒã‚るキーã§çµ‚ã£ã¦ã„ã‚‹ã‹èª¿ã¹ã‚‹ã«ã¯ã€é–¢æ•° `cbstrbwmatch' を用ã„る。

int cbstrbwmatch(const char *str, const char *key);
`str' ã¯å¯¾è±¡ã®æ–‡å­—列ã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`key' ã¯å¾Œæ–¹ä¸€è‡´ã®ã‚­ãƒ¼ã®æ–‡å­—列ã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚戻り値ã¯å¯¾è±¡ã®æ–‡å­—列ãŒã‚­ãƒ¼ã§çµ‚ã£ã¦ã„れã°çœŸã€ãã†ã§ãªã‘れã°å½ã§ã‚る。

大文字ã¨å°æ–‡å­—ã®é•ã„を無視ã—ã¤ã¤ã€æ–‡å­—列ãŒã‚るキーã§çµ‚ã£ã¦ã„ã‚‹ã‹èª¿ã¹ã‚‹ã«ã¯ã€é–¢æ•° `cbstrbwimatch' を用ã„る。

int cbstrbwimatch(const char *str, const char *key);
`str' ã¯å¯¾è±¡ã®æ–‡å­—列ã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`key' ã¯å¾Œæ–¹ä¸€è‡´ã®ã‚­ãƒ¼ã®æ–‡å­—列ã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚戻り値ã¯å¯¾è±¡ã®æ–‡å­—列ãŒã‚­ãƒ¼ã§çµ‚ã£ã¦ã„れã°çœŸã€ãã†ã§ãªã‘れã°å½ã§ã‚る。ASCIIコード中ã®ã‚¢ãƒ«ãƒ•ァベットã®å¤§æ–‡å­—ã¨å°æ–‡å­—ã¯åŒºåˆ¥ã•れãªã„。

KMP法を用ã„ã¦æ–‡å­—列ã®éƒ¨åˆ†æ–‡å­—列ã®ä½ç½®ã‚’å¾—ã‚‹ã«ã¯ã€é–¢æ•° `cbstrstrkmp' を用ã„る。

char *cbstrstrkmp(const char *haystack, const char *needle);
`haystack' ã¯æ–‡å­—列ã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`needle' ã¯æŽ¢ã™ã¹ã部分文字列ã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚戻り値ã¯éƒ¨åˆ†æ–‡å­—列ã®é–‹å§‹ã‚’指ã™ãƒã‚¤ãƒ³ã‚¿ã‹ã€è¦‹ã¤ã‹ã‚‰ãªã‘れ㰠`NULL' ã§ã‚る。大抵ã®å ´åˆã€ã“ã®é–¢æ•°ã‚ˆã‚Šã‚³ãƒ³ãƒ‘イラã®ãƒ“ルドインã§ã‚ã‚‹ `strstr' ã®æ–¹ãŒé«˜é€Ÿã§ã‚る。

BM法を用ã„ã¦æ–‡å­—列ã®éƒ¨åˆ†æ–‡å­—列ã®ä½ç½®ã‚’å¾—ã‚‹ã«ã¯ã€é–¢æ•° `cbstrstrbm' を用ã„る。

char *cbstrstrbm(const char *haystack, const char *needle);
`haystack' ã¯æ–‡å­—列ã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`needle' ã¯æŽ¢ã™ã¹ã部分文字列ã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚戻り値ã¯éƒ¨åˆ†æ–‡å­—列ã®é–‹å§‹ã‚’指ã™ãƒã‚¤ãƒ³ã‚¿ã‹ã€è¦‹ã¤ã‹ã‚‰ãªã‘れ㰠`NULL' ã§ã‚る。大抵ã®å ´åˆã€ã“ã®é–¢æ•°ã‚ˆã‚Šã‚³ãƒ³ãƒ‘イラã®ãƒ“ルドインã§ã‚ã‚‹ `strstr' ã®æ–¹ãŒé«˜é€Ÿã§ã‚る。

文字列ã®å…¨ã¦ã®æ–‡å­—を大文字ã«å¤‰æ›ã™ã‚‹ã«ã¯ã€é–¢æ•° `cbstrtoupper' を用ã„る。

char *cbstrtoupper(char *str);
`str' ã¯å¤‰æ›å¯¾è±¡ã®æ–‡å­—列ã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚戻り値ã¯ãã®æ–‡å­—列ã¸ã®ãƒã‚¤ãƒ³ã‚¿ã§ã‚る。

文字列ã®å…¨ã¦ã®æ–‡å­—ã‚’å°æ–‡å­—ã«å¤‰æ›ã™ã‚‹ã«ã¯ã€é–¢æ•° `cbstrtolower' を用ã„る。

char *cbstrtolower(char *str);
`str' ã¯å¤‰æ›å¯¾è±¡ã®æ–‡å­—列ã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚戻り値ã¯ãã®æ–‡å­—列ã¸ã®ãƒã‚¤ãƒ³ã‚¿ã§ã‚る。

文字列ã®å…ˆé ­ã¨æœ«å°¾ã«ã‚る空白文字を削除ã™ã‚‹ã«ã¯ã€é–¢æ•° `cbstrtrim' を用ã„る。

char *cbstrtrim(char *str);
`str' ã¯å¤‰æ›å¯¾è±¡ã®æ–‡å­—列ã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚戻り値ã¯ãã®æ–‡å­—列ã¸ã®ãƒã‚¤ãƒ³ã‚¿ã§ã‚る。

文字列内ã®é€£ç¶šã™ã‚‹ç©ºç™½ã‚’絞ã£ã¦æ•´å½¢ã™ã‚‹ã«ã¯ã€é–¢æ•° `cbstrsqzcpc' を用ã„る。

char *cbstrsqzspc(char *str);
`str' ã¯å¤‰æ›å¯¾è±¡ã®æ–‡å­—列ã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚戻り値ã¯ãã®æ–‡å­—列ã¸ã®ãƒã‚¤ãƒ³ã‚¿ã§ã‚る。

UTF-8ã®æ–‡å­—列ã«å«ã¾ã‚Œã‚‹æ–‡å­—æ•°ã‚’æ•°ãˆã‚‹ã«ã¯ã€é–¢æ•° `cbstrcountutf' を用ã„る。

int cbstrcountutf(const char *str);
`str' ã¯UTF-8ã®æ–‡å­—列ã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚戻り値ã¯ãã®æ–‡å­—列ã«å«ã¾ã‚Œã‚‹æ–‡å­—æ•°ã§ã‚る。

UTF-8ã®æ–‡å­—列を指定ã—ãŸæ–‡å­—æ•°ã§åˆ‡ã‚‹ã«ã¯ã€é–¢æ•° `cbstrcututf' を用ã„る。

char *cbstrcututf(char *str, int num);
`str' ã¯UTF-8ã®æ–‡å­—列ã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`num' ã¯ä¿æŒã™ã‚‹æ–‡å­—数を指定ã™ã‚‹ã€‚戻り値ã¯ãã®æ–‡å­—列ã¸ã®ãƒã‚¤ãƒ³ã‚¿ã§ã‚る。

データãƒãƒ³ãƒ‰ãƒ«ã‚’作æˆã™ã‚‹ã«ã¯ã€é–¢æ•° `cbdatumopen' を用ã„る。

CBDATUM *cbdatumopen(const char *ptr, int size);
`ptr' ã¯åˆæœŸå†…容ã®é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã‹ã€`NULL' ãªã‚‰ç©ºã®ãƒ‡ãƒ¼ã‚¿ã‚’作æˆã™ã‚‹ã€‚`size' ã¯ãã®é ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã‹ã€è² æ•°ãªã‚‰ `strlen(ptr)' ã®å€¤ã¨ãªã‚‹ã€‚戻り値ã¯ãƒ‡ãƒ¼ã‚¿ãƒãƒ³ãƒ‰ãƒ«ã§ã‚る。

データを複製ã™ã‚‹ã«ã¯ã€é–¢æ•° `cbdatumdup' を用ã„る。

CBDATUM *cbdatumdup(const CBDATUM *datum);
`datum' ã¯ãƒ‡ãƒ¼ã‚¿ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ–°ã—ã„データãƒãƒ³ãƒ‰ãƒ«ã§ã‚る。

データãƒãƒ³ãƒ‰ãƒ«ã‚’破棄ã™ã‚‹ã«ã¯ã€é–¢æ•° `cbdatumclose' を用ã„る。

void cbdatumclose(CBDATUM *datum);
`datum' ã¯ãƒ‡ãƒ¼ã‚¿ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚é–‰ã˜ãŸãƒãƒ³ãƒ‰ãƒ«ã®é ˜åŸŸã¯è§£æ”¾ã•れるã®ã§ã€ä»¥å¾Œã¯åˆ©ç”¨ã™ã‚‹ã“ã¨ãŒã§ããªããªã‚‹ã€‚

データã«åˆ¥ã®é ˜åŸŸã‚’連çµã™ã‚‹ã«ã¯ã€é–¢æ•° `cbdatumcat' を用ã„る。

void cbdatumcat(CBDATUM *datum, const char *ptr, int size);
`datum' ã¯ãƒ‡ãƒ¼ã‚¿ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`ptr' ã¯é€£çµã™ã‚‹é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`size' ã¯ãã®é ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã‹ã€è² æ•°ãªã‚‰ `strlen(ptr)' ã®å€¤ã¨ãªã‚‹ã€‚

データã®é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’å¾—ã‚‹ã«ã¯ã€é–¢æ•° `cbdatumptr' を用ã„る。

const char *cbdatumptr(const CBDATUM *datum);
`datum' ã¯ãƒ‡ãƒ¼ã‚¿ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚戻り値ã¯ãƒ‡ãƒ¼ã‚¿ã®é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã§ã‚る。戻り値ã®é ˜åŸŸã¯ã€å®Ÿéš›ã«ã¯1ãƒã‚¤ãƒˆå¤šã確ä¿ã—ã¦çµ‚端文字ãŒç½®ã‹ã‚Œã‚‹ã®ã§ã€æ–‡å­—列ã¨ã—ã¦åˆ©ç”¨ã§ãる。

データã®é ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’å¾—ã‚‹ã«ã¯ã€é–¢æ•° `cbdatumsize' を用ã„る。

int cbdatumsize(const CBDATUM *datum);
`datum' ã¯ãƒ‡ãƒ¼ã‚¿ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚戻り値ã¯ãƒ‡ãƒ¼ã‚¿ã®é ˜åŸŸã®ã‚µã‚¤ã‚ºã§ã‚る。

データã®é ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’変更ã™ã‚‹ã«ã¯ã€é–¢æ•° `cbdatumsetsize' を用ã„る。

void cbdatumsetsize(CBDATUM *datum, int size);
`datum' ã¯ãƒ‡ãƒ¼ã‚¿ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`size' ã¯é ˜åŸŸã®æ–°ã—ã„サイズを指定ã™ã‚‹ã€‚æ–°ã—ã„ã‚µã‚¤ã‚ºãŒæ—¢å­˜ã®ã‚µã‚¤ã‚ºã‚ˆã‚Šå¤§ãã„å ´åˆã€ä½™ã£ãŸé ˜åŸŸã¯çµ‚端文字ã§åŸ‹ã‚られる。

ãƒ‡ãƒ¼ã‚¿ã«æ›¸å¼å‡ºåŠ›ã‚’è¡Œãªã†ã«ã¯ã€é–¢æ•° `cbdatumprintf' を用ã„る。

void cbdatumprintf(CBDATUM *datum, const char *format, ...);
`format' ã¯printfé¢¨ã®æ›¸å¼æ–‡å­—列を指定ã™ã‚‹ã€‚å¤‰æ›æ–‡å­— `%' ã‚’ `s'ã€`d'ã€`o'ã€`u'ã€`x'ã€`X'ã€`c'ã€`e'ã€`E'ã€`f'ã€`g'ã€`G'ã€`@'ã€`?'ã€`:'ã€`%' ã¨ä½µã›ã¦åˆ©ç”¨ã™ã‚‹ã“ã¨ãŒã§ãる。`@' 㯠`s' ã¨åŒæ§˜ã«æ©Ÿèƒ½ã™ã‚‹ãŒã€XMLã®ãƒ¡ã‚¿æ–‡å­—をエスケープã™ã‚‹ã€‚`?' 㯠`s' ã¨åŒæ§˜ã«æ©Ÿèƒ½ã™ã‚‹ãŒã€URLã®ãƒ¡ã‚¿æ–‡å­—をエスケープã™ã‚‹ã€‚`:' 㯠`s' ã¨åŒæ§˜ã«æ©Ÿèƒ½ã™ã‚‹ãŒã€UTF-8ã¨ã—ã¦ã®MIMEエンコーディングを施ã™ã€‚ãれ以外ã®å¤‰æ›æ–‡å­—ã¯å…ƒæ¥ã®ã‚‚ã®ã¨åŒæ§˜ã«æ©Ÿèƒ½ã™ã‚‹ã€‚

データを確ä¿ã•れãŸé ˜åŸŸã«å¤‰æ›ã™ã‚‹ã«ã¯ã€é–¢æ•° `cbdatumtomalloc' を用ã„る。

char *cbdatumtomalloc(CBDATUM *datum, int *sp);
`datum' ã¯ãƒ‡ãƒ¼ã‚¿ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`sp' ㌠`NULL' ã§ãªã‘れã°ã€ãã®å‚ç…§å…ˆã«æŠ½å‡ºã—ãŸé ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’æ ¼ç´ã™ã‚‹ã€‚戻り値ã¯ãƒ‡ãƒ¼ã‚¿ã®é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã§ã‚る。戻り値ã®é ˜åŸŸã¯ã€å®Ÿéš›ã«ã¯1ãƒã‚¤ãƒˆå¤šã確ä¿ã—ã¦çµ‚端文字ãŒç½®ã‹ã‚Œã‚‹ã®ã§ã€æ–‡å­—列ã¨ã—ã¦åˆ©ç”¨ã§ãる。戻り値ã®é ˜åŸŸã¯ `malloc' ã§ç¢ºä¿ã•れるã®ã§ã€ä¸è¦ã«ãªã£ãŸã‚‰ `free' ã§è§£æ”¾ã™ã‚‹ã¹ãã§ã‚る。元ã®ãƒ‡ãƒ¼ã‚¿ã®é ˜åŸŸã¯è§£æ”¾ã•れるã®ã§ã€ãれをå†ã³è§£æ”¾ã—ã¦ã¯ãªã‚‰ãªã„。

リストãƒãƒ³ãƒ‰ãƒ«ã‚’作æˆã™ã‚‹ã«ã¯ã€é–¢æ•° `cblistopen' を用ã„る。

CBLIST *cblistopen(void);
戻り値ã¯ãƒªã‚¹ãƒˆãƒãƒ³ãƒ‰ãƒ«ã§ã‚る。

リストを複製ã™ã‚‹ã«ã¯ã€é–¢æ•° `cblistdup' を用ã„る。

CBLIST *cblistdup(const CBLIST *list);
`list' ã¯ãƒªã‚¹ãƒˆãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ–°ã—ã„リストãƒãƒ³ãƒ‰ãƒ«ã§ã‚る。

リストãƒãƒ³ãƒ‰ãƒ«ã‚’破棄ã™ã‚‹ã«ã¯ã€é–¢æ•° `cblistclose' を用ã„る。

void cblistclose(CBLIST *list);
`list' ã¯ãƒªã‚¹ãƒˆãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚é–‰ã˜ãŸãƒãƒ³ãƒ‰ãƒ«ã®é ˜åŸŸã¯è§£æ”¾ã•れるã®ã§ã€ä»¥å¾Œã¯åˆ©ç”¨ã™ã‚‹ã“ã¨ãŒã§ããªããªã‚‹ã€‚

ãƒªã‚¹ãƒˆã«æ ¼ç´ã•れãŸè¦ç´ æ•°ã‚’å¾—ã‚‹ã«ã¯ã€é–¢æ•° `cblistnum' を用ã„る。

int cblistnum(const CBLIST *list);
`list' ã¯ãƒªã‚¹ãƒˆãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚戻り値ã¯ãƒªã‚¹ãƒˆã«æ ¼ç´ã•れãŸè¦ç´ æ•°ã§ã‚る。

リスト内ã®ã‚ã‚‹è¦ç´ ã®é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’å¾—ã‚‹ã«ã¯ã€é–¢æ•° `cblistval' を用ã„る。

const char *cblistval(const CBLIST *list, int index, int *sp);
`list' ã¯ãƒªã‚¹ãƒˆãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`index' ã¯å–り出ã™è¦ç´ ã®ã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹ã‚’指定ã™ã‚‹ã€‚`sp' ㌠`NULL' ã§ãªã‘れã°ã€ãã®å‚ç…§å…ˆã«æŠ½å‡ºã—ãŸé ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’æ ¼ç´ã™ã‚‹ã€‚戻り値ã¯è©²å½“è¦ç´ ã®é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã§ã‚る。戻り値ã®é ˜åŸŸã¯ã€å®Ÿéš›ã«ã¯1ãƒã‚¤ãƒˆå¤šã確ä¿ã—ã¦çµ‚端文字ãŒç½®ã‹ã‚Œã‚‹ã®ã§ã€æ–‡å­—列ã¨ã—ã¦åˆ©ç”¨ã§ãる。`index' ãŒè¦ç´ æ•°ä»¥ä¸Šãªã‚‰ã°ã€æˆ»ã‚Šå€¤ã¯ `NULL' ã§ã‚る。

è¦ç´ ã‚’ãƒªã‚¹ãƒˆã®æœ«å°¾ã«åŠ ãˆã‚‹ã«ã¯ã€é–¢æ•° `cblistpush' を用ã„る。

void cblistpush(CBLIST *list, const char *ptr, int size);
`list' ã¯ãƒªã‚¹ãƒˆãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`ptr' ã¯è¿½åŠ ã™ã‚‹è¦ç´ ã®é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`size' ã¯ãã®é ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ãŒã€è² æ•°ãªã‚‰ `strlen(ptr)' ã®å€¤ã¨ãªã‚‹ã€‚

ãƒªã‚¹ãƒˆã®æœ«å°¾ã®è¦ç´ ã‚’削除ã™ã‚‹ã«ã¯ã€é–¢æ•° `cblistpop' を用ã„る。

char *cblistpop(CBLIST *list, int *sp);
`list' ã¯ãƒªã‚¹ãƒˆãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`sp' ㌠`NULL' ã§ãªã‘れã°ã€ãã®å‚ç…§å…ˆã«æŠ½å‡ºã—ãŸé ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’æ ¼ç´ã™ã‚‹ã€‚戻り値ã¯è©²å½“è¦ç´ ã®é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã§ã‚る。戻り値ã®é ˜åŸŸã¯ã€å®Ÿéš›ã«ã¯1ãƒã‚¤ãƒˆå¤šã確ä¿ã—ã¦çµ‚端文字ãŒç½®ã‹ã‚Œã‚‹ã®ã§ã€æ–‡å­—列ã¨ã—ã¦åˆ©ç”¨ã§ãる。戻り値ã®é ˜åŸŸã¯ `malloc' ã§ç¢ºä¿ã•れるã®ã§ã€ä¸è¦ã«ãªã£ãŸã‚‰ `free' ã§è§£æ”¾ã™ã‚‹ã¹ãã§ã‚る。リストãŒç©ºãªã‚‰ã°ã€æˆ»ã‚Šå€¤ã¯ `NULL' ã§ã‚る。

è¦ç´ ã‚’リストã®å…ˆé ­ã«åŠ ãˆã‚‹ã«ã¯ã€é–¢æ•° `cblistunshift' を用ã„る。

void cblistunshift(CBLIST *list, const char *ptr, int size);
`list' ã¯ãƒªã‚¹ãƒˆãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`ptr' ã¯è¿½åŠ ã™ã‚‹è¦ç´ ã®é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`size' ã¯ãã®é ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ãŒã€è² æ•°ãªã‚‰ `strlen(ptr)' ã®å€¤ã¨ãªã‚‹ã€‚

リストã®å…ˆé ­ã®è¦ç´ ã‚’削除ã™ã‚‹ã«ã¯ã€é–¢æ•° `cblistshift' を用ã„る。

char *cblistshift(CBLIST *list, int *sp);
`list' ã¯ãƒªã‚¹ãƒˆãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`sp' ㌠`NULL' ã§ãªã‘れã°ã€ãã®å‚ç…§å…ˆã«æŠ½å‡ºã—ãŸé ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’æ ¼ç´ã™ã‚‹ã€‚戻り値ã¯è©²å½“è¦ç´ ã®é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã§ã‚る。戻り値ã®é ˜åŸŸã¯ã€å®Ÿéš›ã«ã¯1ãƒã‚¤ãƒˆå¤šã確ä¿ã—ã¦çµ‚端文字ãŒç½®ã‹ã‚Œã‚‹ã®ã§ã€æ–‡å­—列ã¨ã—ã¦åˆ©ç”¨ã§ãる。戻り値ã®é ˜åŸŸã¯ `malloc' ã§ç¢ºä¿ã•れるã®ã§ã€ä¸è¦ã«ãªã£ãŸã‚‰ `free' ã§è§£æ”¾ã™ã‚‹ã¹ãã§ã‚る。リストãŒç©ºãªã‚‰ã°ã€æˆ»ã‚Šå€¤ã¯ `NULL' ã§ã‚る。

ãƒªã‚¹ãƒˆå†…ã®æŒ‡å®šã—ãŸä½ç½®ã«è¦ç´ ã‚’加ãˆã‚‹ã«ã¯ã€é–¢æ•° `cblistinsert' を用ã„る。

void cblistinsert(CBLIST *list, int index, const char *ptr, int size);
`list' ã¯ãƒªã‚¹ãƒˆãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`index' ã¯è¿½åŠ ã™ã‚‹è¦ç´ ã®ã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹ã‚’指定ã™ã‚‹ã€‚`ptr' ã¯è¿½åŠ ã™ã‚‹è¦ç´ ã®é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`size' ã¯ãã®é ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ãŒã€è² æ•°ãªã‚‰ `strlen(ptr)' ã®å€¤ã¨ãªã‚‹ã€‚

ãƒªã‚¹ãƒˆå†…ã®æŒ‡å®šã—ãŸä½ç½®ã®è¦ç´ ã‚’削除ã™ã‚‹ã«ã¯ã€é–¢æ•° `cblistremove' を用ã„る。

char *cblistremove(CBLIST *list, int index, int *sp);
`list' ã¯ãƒªã‚¹ãƒˆãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`index' ã¯å‰Šé™¤ã™ã‚‹è¦ç´ ã®ã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹ã‚’指定ã™ã‚‹ã€‚`sp' ㌠`NULL' ã§ãªã‘れã°ã€ãã®å‚ç…§å…ˆã«æŠ½å‡ºã—ãŸé ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’æ ¼ç´ã™ã‚‹ã€‚戻り値ã¯è©²å½“è¦ç´ ã®é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã§ã‚る。戻り値ã®é ˜åŸŸã¯ã€å®Ÿéš›ã«ã¯1ãƒã‚¤ãƒˆå¤šã確ä¿ã—ã¦çµ‚端文字ãŒç½®ã‹ã‚Œã‚‹ã®ã§ã€æ–‡å­—列ã¨ã—ã¦åˆ©ç”¨ã§ãる。戻り値ã®é ˜åŸŸã¯ `malloc' ã§ç¢ºä¿ã•れるã®ã§ã€ä¸è¦ã«ãªã£ãŸã‚‰ `free' ã§è§£æ”¾ã™ã‚‹ã¹ãã§ã‚る。`index' ãŒè¦ç´ æ•°ä»¥ä¸Šãªã‚‰ã°ã€è¦ç´ ã¯å‰Šé™¤ã•れãšã€æˆ»ã‚Šå€¤ã¯ `NULL' ã§ã‚る。

ãƒªã‚¹ãƒˆå†…ã®æŒ‡å®šã—ãŸä½ç½®ã®è¦ç´ ã‚’上書ãã™ã‚‹ã«ã¯ã€é–¢æ•° `cblistover' を用ã„る。

void cblistover(CBLIST *list, int index, const char *ptr, int size);
`list' ã¯ãƒªã‚¹ãƒˆãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`index' ã¯å‰Šé™¤ã™ã‚‹è¦ç´ ã®ã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹ã‚’指定ã™ã‚‹ã€‚`ptr' ã¯æ–°ã—ã„内容ã®é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`size' ã¯ãã®é ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ãŒã€è² æ•°ãªã‚‰ `strlen(ptr)' ã®å€¤ã¨ãªã‚‹ã€‚`index' ãŒè¦ç´ æ•°ä»¥ä¸Šãªã‚‰ã°ã€ã“ã®é–¢æ•°ã¯ä½•ã‚‚ã—ãªã„。

リストã®è¦ç´ ã‚’è¾žæ›¸é †ã§æ•´åˆ—ã•ã›ã‚‹ã«ã¯ã€é–¢æ•° `cblistsort' を用ã„る。

void cblistsort(CBLIST *list);
`list' ã¯ãƒªã‚¹ãƒˆãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚整列ã«ã¯ã‚¯ã‚¤ãƒƒã‚¯ã‚½ãƒ¼ãƒˆãŒç”¨ã„られる。

リストã®è¦ç´ ã‚’線形探索を使ã£ã¦æ¤œç´¢ã™ã‚‹ã«ã¯ã€é–¢æ•° `cblistlsearch' を用ã„る。

int cblistlsearch(const CBLIST *list, const char *ptr, int size);
`list' ã¯ãƒªã‚¹ãƒˆãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`ptr' ã¯æ¤œç´¢ã‚­ãƒ¼ã®é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`size' ã¯ãã®é ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ãŒã€è² æ•°ãªã‚‰ `strlen(ptr)' ã®å€¤ã¨ãªã‚‹ã€‚戻り値ã¯è©²å½“ã®è¦ç´ ã®ã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹ã§ã‚ã‚‹ãŒã€è©²å½“ãŒãªã‘れ㰠-1 ã§ã‚る。複数ã®è¦ç´ ãŒè©²å½“ã—ãŸå ´åˆã€å‰è€…ãŒè¿”ã•れる。

リストã®è¦ç´ ã‚’二分探索を使ã£ã¦æ¤œç´¢ã™ã‚‹ã«ã¯ã€é–¢æ•° `cblistbsearch' を用ã„る。

int cblistbsearch(const CBLIST *list, const char *ptr, int size);
`list' ã¯ãƒªã‚¹ãƒˆãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚リストã¯è¾žæ›¸é †ã«ã‚½ãƒ¼ãƒˆã•れã¦ã„ã‚‹å¿…è¦ãŒã‚る。`ptr' ã¯æ¤œç´¢ã‚­ãƒ¼ã®é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`size' ã¯ãã®é ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ãŒã€è² æ•°ãªã‚‰ `strlen(ptr)' ã®å€¤ã¨ãªã‚‹ã€‚戻り値ã¯è©²å½“ã®è¦ç´ ã®ã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹ã§ã‚ã‚‹ãŒã€è©²å½“ãŒãªã‘れ㰠-1 ã§ã‚る。複数ã®è¦ç´ ãŒè©²å½“ã—ãŸå ´åˆã«ã©ã¡ã‚‰ãŒè¿”ã‚‹ã‹ã¯æœªå®šç¾©ã§ã‚る。

リストを直列化ã—ã¦ãƒã‚¤ãƒˆé…列ã«ã™ã‚‹ã«ã¯ã€é–¢æ•° `cblistdump' を用ã„る。

char *cblistdump(const CBLIST *list, int *sp);
`list' ã¯ãƒªã‚¹ãƒˆãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`sp' ã¯æŠ½å‡ºã—ãŸé ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’æ ¼ç´ã™ã‚‹é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚戻り値ã¯ç›´åˆ—化ã•れãŸé ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã§ã‚る。戻り値ã®é ˜åŸŸã¯ `malloc' ã§ç¢ºä¿ã•れるã®ã§ã€ä¸è¦ã«ãªã£ãŸã‚‰ `free' ã§è§£æ”¾ã™ã‚‹ã¹ãã§ã‚る。

直列化ã•れãŸãƒªã‚¹ãƒˆã‚’復元ã™ã‚‹ã«ã¯ã€é–¢æ•° `cblistload' を用ã„る。

CBLIST *cblistload(const char *ptr, int size);
`ptr' ã¯ãƒã‚¤ãƒˆé…列ã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`size' ã¯ãã®é ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ–°ã—ã„リストãƒãƒ³ãƒ‰ãƒ«ã§ã‚る。

マップãƒãƒ³ãƒ‰ãƒ«ã‚’作æˆã™ã‚‹ã«ã¯ã€é–¢æ•° `cbmapopen' を用ã„る。

CBMAP *cbmapopen(void);
戻り値ã¯ãƒžãƒƒãƒ—ãƒãƒ³ãƒ‰ãƒ«ã§ã‚る。

マップを複製ã™ã‚‹ã«ã¯ã€é–¢æ•° `cbmapdup' を用ã„る。

CBMAP *cbmapdup(CBMAP *map);
`map' ã¯ãƒžãƒƒãƒ—ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ–°ã—ã„マップãƒãƒ³ãƒ‰ãƒ«ã§ã‚る。コピー元ã®ãƒžãƒƒãƒ—ã®ã‚¤ãƒ†ãƒ¬ãƒ¼ã‚¿ã¯åˆæœŸåŒ–ã•れる。

マップãƒãƒ³ãƒ‰ãƒ«ã‚’破棄ã™ã‚‹ã«ã¯ã€é–¢æ•° `cbmapclose' を用ã„る。

void cbmapclose(CBMAP *map);
`map' ã¯ãƒžãƒƒãƒ—ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚é–‰ã˜ãŸãƒãƒ³ãƒ‰ãƒ«ã®é ˜åŸŸã¯è§£æ”¾ã•れるã®ã§ã€ä»¥å¾Œã¯åˆ©ç”¨ã§ããªããªã‚‹ã€‚

マップã«ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’追加ã™ã‚‹ã«ã¯ã€é–¢æ•° `cbmapput' を用ã„る。

int cbmapput(CBMAP *map, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int over);
`map' ã¯ãƒžãƒƒãƒ—ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`kbuf' ã¯ã‚­ãƒ¼ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`ksiz' ã¯ã‚­ãƒ¼ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã‹ã€è² æ•°ãªã‚‰ `strlen(kbuf)' ã®å€¤ã¨ãªã‚‹ã€‚`vbuf' ã¯å€¤ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`vsiz' ã¯å€¤ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã‹ã€è² æ•°ãªã‚‰ `strlen(vbuf)' ã®å€¤ã¨ãªã‚‹ã€‚`over' ã¯é‡è¤‡ã—ãŸãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’上書ãã™ã‚‹ã‹å¦ã‹ã‚’指定ã™ã‚‹ã€‚`over' ãŒå½ã§ã‚­ãƒ¼ãŒé‡è¤‡ã—ãŸå ´åˆã¯æˆ»ã‚Šå€¤ã¯å½ã§ã‚ã‚‹ãŒã€ãã†ã§ãªã„å ´åˆã¯çœŸã§ã‚る。

既存ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã®å€¤ã®æœ«å°¾ã«å€¤ã‚’連çµã™ã‚‹ã«ã¯ã€é–¢æ•° `cbmapputcat' を用ã„る。

void cbmapputcat(CBMAP *map, const char *kbuf, int ksiz, const char *vbuf, int vsiz);
`map' ã¯ãƒžãƒƒãƒ—ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`kbuf' ã¯ã‚­ãƒ¼ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`ksiz' ã¯ã‚­ãƒ¼ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã‹ã€è² æ•°ãªã‚‰ `strlen(kbuf)' ã®å€¤ã¨ãªã‚‹ã€‚`vbuf' ã¯å€¤ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`vsiz' ã¯å€¤ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã‹ã€è² æ•°ãªã‚‰ `strlen(vbuf)' ã®å€¤ã¨ãªã‚‹ã€‚該当ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ãŒå­˜åœ¨ã—ãªã„å ´åˆã¯æ–°ã—ã„レコードãŒä½œã‚‰ã‚Œã‚‹ã€‚

マップã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’削除ã™ã‚‹ã«ã¯ã€é–¢æ•° `cbmapout' を用ã„る。

int cbmapout(CBMAP *map, const char *kbuf, int ksiz);
`map' ã¯ãƒžãƒƒãƒ—ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`kbuf' ã¯ã‚­ãƒ¼ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`ksiz' ã¯ã‚­ãƒ¼ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã‹ã€è² æ•°ãªã‚‰ `strlen(kbuf)' ã®å€¤ã¨ãªã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰çœŸã§ã‚りã€è©²å½“ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ãŒãªã„å ´åˆã¯å½ã§ã‚る。

マップã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’å–å¾—ã™ã‚‹ã«ã¯ã€é–¢æ•° `cbmapget' を用ã„る。

const char *cbmapget(const CBMAP *map, const char *kbuf, int ksiz, int *sp);
`map' ã¯ãƒžãƒƒãƒ—ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`kbuf' ã¯ã‚­ãƒ¼ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`ksiz' ã¯ã‚­ãƒ¼ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã‹ã€è² æ•°ãªã‚‰ `strlen(kbuf)' ã®å€¤ã¨ãªã‚‹ã€‚`sp' ㌠`NULL' ã§ãªã‘れã°ã€ãã®å‚ç…§å…ˆã«æŠ½å‡ºã—ãŸé ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’æ ¼ç´ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰å€¤ã‚’æ ¼ç´ã—ãŸé ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã§ã‚りã€è©²å½“ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ãŒãªã„å ´åˆã¯ `NULL' ã§ã‚る。戻り値ã®é ˜åŸŸã¯ã€å®Ÿéš›ã«ã¯1ãƒã‚¤ãƒˆå¤šã確ä¿ã—ã¦çµ‚端文字ãŒç½®ã‹ã‚Œã‚‹ã®ã§ã€æ–‡å­—列ã¨ã—ã¦åˆ©ç”¨ã§ãる。

レコードをマップã®ç«¯ã«ç§»å‹•ã•ã›ã‚‹ã«ã¯ã€é–¢æ•° `cbmapmove' を用ã„る。

int cbmapmove(CBMAP *map, const char *kbuf, int ksiz, int head);
`map' ã¯ãƒžãƒƒãƒ—ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`kbuf' ã¯ã‚­ãƒ¼ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`ksiz' ã¯ã‚­ãƒ¼ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã‹ã€è² æ•°ãªã‚‰ `strlen(kbuf)' ã®å€¤ã¨ãªã‚‹ã€‚`head' ã¯ç§»å‹•先を指定ã—ã€çœŸãªã‚‰å…ˆé ­ã€å½ãªã‚‰æœ«å°¾ã¨ãªã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰çœŸã§ã‚りã€è©²å½“ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ãŒãªã„å ´åˆã¯å½ã§ã‚る。

マップã®ã‚¤ãƒ†ãƒ¬ãƒ¼ã‚¿ã‚’åˆæœŸåŒ–ã™ã‚‹ã«ã¯ã€é–¢æ•° `cbmapiterinit' を用ã„る。

void cbmapiterinit(CBMAP *map);
`map' ã¯ãƒžãƒƒãƒ—ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚イテレータã¯ã€ãƒžãƒƒãƒ—ã«æ ¼ç´ã•れãŸå…¨ã¦ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’å‚ç…§ã™ã‚‹ãŸã‚ã«ç”¨ã„られる。

マップã®ã‚¤ãƒ†ãƒ¬ãƒ¼ã‚¿ã‹ã‚‰æ¬¡ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã®ã‚­ãƒ¼ã‚’å–り出ã™ã«ã¯ã€é–¢æ•° `cbmapiternext' を用ã„る。

const char *cbmapiternext(CBMAP *map, int *sp);
`map' ã¯ãƒžãƒƒãƒ—ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`sp' ㌠`NULL' ã§ãªã‘れã°ã€ãã®å‚ç…§å…ˆã«æŠ½å‡ºã—ãŸé ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’æ ¼ç´ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰ã‚­ãƒ¼ã‚’æ ¼ç´ã—ãŸé ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰ `NULL' ã§ã‚ã‚‹ã€‚ã‚¤ãƒ†ãƒ¬ãƒ¼ã‚¿ãŒæœ€å¾Œã¾ã§ãã¦è©²å½“ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ãŒãªã„å ´åˆã‚‚ `NULL' ã‚’è¿”ã™ã€‚戻り値ã®é ˜åŸŸã¯ã€å®Ÿéš›ã«ã¯1ãƒã‚¤ãƒˆå¤šã確ä¿ã—ã¦çµ‚端文字ãŒç½®ã‹ã‚Œã‚‹ã®ã§ã€æ–‡å­—列ã¨ã—ã¦åˆ©ç”¨ã§ãる。å–り出ã™é †ç•ªã¯æ ¼ç´ã—ãŸéš›ã®é †ç•ªã«ä¸€è‡´ã™ã‚‹ã“ã¨ãŒä¿è¨¼ã•れã¦ã„る。

マップã®ã‚¤ãƒ†ãƒ¬ãƒ¼ã‚¿ã‹ã‚‰å–り出ã—ãŸã‚­ãƒ¼ã«å¯¾å¿œã™ã‚‹å€¤ã‚’å–り出ã™ã«ã¯ã€é–¢æ•°ã€€`cbmapiterval' を用ã„る。

const char *cbmapiterval(const char *kbuf, int *sp);
`kbuf' ã¯ã‚¤ãƒ†ãƒ¬ãƒ¼ã‚¿ã‹ã‚‰å–り出ã—ãŸã‚­ãƒ¼ã®é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`sp' ㌠`NULL' ã§ãªã‘れã°ã€ãã®å‚ç…§å…ˆã«æŠ½å‡ºã—ãŸé ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’æ ¼ç´ã™ã‚‹ã€‚戻り値ã¯å€¤ã‚’æ ¼ç´ã—ãŸé ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã§ã‚る。戻り値ã®é ˜åŸŸã¯ã€å®Ÿéš›ã«ã¯1ãƒã‚¤ãƒˆå¤šã確ä¿ã—ã¦çµ‚端文字ãŒç½®ã‹ã‚Œã‚‹ã®ã§ã€æ–‡å­—列ã¨ã—ã¦åˆ©ç”¨ã§ãる。

マップã®ãƒ¬ã‚³ãƒ¼ãƒ‰æ•°ã‚’å¾—ã‚‹ã«ã¯ã€é–¢æ•° `cbmaprnum' を用ã„る。

int cbmaprnum(const CBMAP *map);
`map' ã¯ãƒžãƒƒãƒ—ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚戻り値ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®ãƒ¬ã‚³ãƒ¼ãƒ‰æ•°ã§ã‚る。

マップã«å«ã¾ã‚Œã‚‹å…¨ã¦ã®ã‚­ãƒ¼ã‚’å«ã‚€ãƒªã‚¹ãƒˆã‚’å¾—ã‚‹ã«ã¯ã€é–¢æ•° `cbmapkeys' を用ã„る。

CBLIST *cbmapkeys(CBMAP *map);
`map' ã¯ãƒžãƒƒãƒ—ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚戻り値ã¯ãƒžãƒƒãƒ—ã«å«ã¾ã‚Œã‚‹å…¨ã¦ã®ã‚­ãƒ¼ã‚’å«ã‚€ãƒªã‚¹ãƒˆãƒãƒ³ãƒ‰ãƒ«ã§ã‚る。戻り値ã®ãƒãƒ³ãƒ‰ãƒ«ã¯é–¢æ•° `cblistopen' ã§é–‹ã‹ã‚Œã‚‹ã®ã§ã€ä¸è¦ã«ãªã£ãŸã‚‰ `cblistclose' ã§é–‰ã˜ã‚‹ã¹ãã§ã‚る。

マップã«å«ã¾ã‚Œã‚‹å…¨ã¦ã®å€¤ã‚’å«ã‚€ãƒªã‚¹ãƒˆã‚’å¾—ã‚‹ã«ã¯ã€é–¢æ•° `cbmapvals' を用ã„る。

CBLIST *cbmapvals(CBMAP *map);
`map' ã¯ãƒžãƒƒãƒ—ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚戻り値ã¯ãƒžãƒƒãƒ—ã«å«ã¾ã‚Œã‚‹å…¨ã¦ã®å€¤ã‚’å«ã‚€ãƒªã‚¹ãƒˆãƒãƒ³ãƒ‰ãƒ«ã§ã‚る。戻り値ã®ãƒãƒ³ãƒ‰ãƒ«ã¯é–¢æ•° `cblistopen' ã§é–‹ã‹ã‚Œã‚‹ã®ã§ã€ä¸è¦ã«ãªã£ãŸã‚‰ `cblistclose' ã§é–‰ã˜ã‚‹ã¹ãã§ã‚る。

マップを直列化ã—ã¦ãƒã‚¤ãƒˆé…列ã«ã™ã‚‹ã«ã¯ã€é–¢æ•° `cbmapdump' を用ã„る。

char *cbmapdump(const CBMAP *map, int *sp);
`map' ã¯ãƒžãƒƒãƒ—ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`sp' ã¯æŠ½å‡ºã—ãŸé ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’æ ¼ç´ã™ã‚‹é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚戻り値ã¯ç›´åˆ—化ã•れãŸé ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã§ã‚る。戻り値ã®é ˜åŸŸã¯ `malloc' ã§ç¢ºä¿ã•れるã®ã§ã€ä¸è¦ã«ãªã£ãŸã‚‰ `free' ã§è§£æ”¾ã™ã‚‹ã¹ãã§ã‚る。

直列化ã•れãŸãƒžãƒƒãƒ—を復元ã™ã‚‹ã«ã¯ã€é–¢æ•° `cbmapload' を用ã„る。

CBMAP *cbmapload(const char *ptr, int size);
`ptr' ã¯ãƒã‚¤ãƒˆé…列ã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`size' ã¯ãã®é ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ–°ã—ã„マップãƒãƒ³ãƒ‰ãƒ«ã§ã‚る。

直列化ã—ãŸãƒžãƒƒãƒ—ã‹ã‚‰ã²ã¨ã¤ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’抽出ã™ã‚‹ã«ã¯ã€é–¢æ•° `cbmaploadone' を用ã„る。

char *cbmaploadone(const char *ptr, int size, const char *kbuf, int ksiz, int *sp);
`ptr' ã¯ãƒã‚¤ãƒˆé…列ã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`size' ã¯ãã®é ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã€‚`kbuf' ã¯ã‚­ãƒ¼ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`ksiz' ã¯ã‚­ãƒ¼ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã‹ã€è² æ•°ãªã‚‰ `strlen(kbuf)' ã®å€¤ã¨ãªã‚‹ã€‚`sp' ㌠`NULL' ã§ãªã‘れã°ã€ãã®å‚ç…§å…ˆã«æŠ½å‡ºã—ãŸé ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’æ ¼ç´ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰å€¤ã‚’æ ¼ç´ã—ãŸé ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã§ã‚りã€è©²å½“ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ãŒãªã„å ´åˆã¯ `NULL' ã§ã‚る。戻り値ã®é ˜åŸŸã¯ã€å®Ÿéš›ã«ã¯1ãƒã‚¤ãƒˆå¤šã確ä¿ã—ã¦çµ‚端文字ãŒç½®ã‹ã‚Œã‚‹ã®ã§ã€æ–‡å­—列ã¨ã—ã¦åˆ©ç”¨ã§ãる。

ヒープãƒãƒ³ãƒ‰ãƒ«ã‚’作æˆã™ã‚‹ã«ã¯ã€é–¢æ•° `cbheapopen' を用ã„る。

CBHEAP *cbheapopen(int size, int max, int(*compar)(const void *, const void *));
`size' ã¯å„レコードã®é ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã€‚`max' ã¯ãƒ’ãƒ¼ãƒ—ã«æ ¼ç´ã™ã‚‹ãƒ¬ã‚³ãƒ¼ãƒ‰ã®æœ€å¤§æ•°ã‚’指定ã™ã‚‹ã€‚`compar' ã¯æ¯”較関数を指定ã™ã‚‹ã€‚二ã¤ã®å¼•æ•°ã¯ãƒ¬ã‚³ãƒ¼ãƒ‰ã¸ã®ãƒã‚¤ãƒ³ã‚¿ã§ã‚る。比較関数ã¯å‰è€…ãŒå¤§ãã‘ã‚Œã°æ­£æ•°ã‚’ã€å¾Œè€…ãŒå¤§ãã‘れã°è² æ•°ã‚’ã€ä¸¡è€…ãŒç­‰ã—ã‘れ㰠0 ã‚’è¿”ã™ã¹ãã§ã‚る。戻り値ã¯ãƒ’ープãƒãƒ³ãƒ‰ãƒ«ã€‚

ヒープãƒãƒ³ãƒ‰ãƒ«ã‚’複製ã™ã‚‹ã«ã¯ã€é–¢æ•° `cbheapdup' を用ã„る。

CBHEAP *cbheapdup(CBHEAP *heap);
`heap' ã¯ãƒ’ープãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ–°ã—ã„ヒープãƒãƒ³ãƒ‰ãƒ«ã§ã‚る。

ヒープãƒãƒ³ãƒ‰ãƒ«ã‚’破棄ã™ã‚‹ã«ã¯ã€é–¢æ•° `cbheapclose' を用ã„る。

void cbheapclose(CBHEAP *heap);
`heap' ã¯ãƒ’ープãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚é–‰ã˜ãŸãƒãƒ³ãƒ‰ãƒ«ã®é ˜åŸŸã¯è§£æ”¾ã•れるã®ã§ã€ä»¥å¾Œã¯åˆ©ç”¨ã™ã‚‹ã“ã¨ãŒã§ããªããªã‚‹ã€‚

ãƒ’ãƒ¼ãƒ—ã«æ ¼ç´ã•れãŸãƒ¬ã‚³ãƒ¼ãƒ‰æ•°ã‚’å¾—ã‚‹ã«ã¯ã€é–¢æ•° `cbheapnum' を用ã„る。

int cbheapnum(CBHEAP *heap);
`heap' ã¯ãƒ’ープãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚戻り値ã¯ãƒªã‚¹ãƒˆã«æ ¼ç´ã•れãŸãƒ¬ã‚³ãƒ¼ãƒ‰æ•°ã§ã‚る。

ヒープã«ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’挿入ã™ã‚‹ã«ã¯ã€é–¢æ•° `cbheapinsert' を用ã„る。

int cbheapinsert(CBHEAP *heap, const void *ptr);
`heap' ã¯ãƒ’ープãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`ptr' ã¯è¿½åŠ ã™ã‚‹ãƒ¬ã‚³ãƒ¼ãƒ‰ã®é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚戻り値ã¯ãƒ¬ã‚³ãƒ¼ãƒ‰ãŒè¿½åŠ ã•れれã°çœŸã§ã‚りã€ãã†ã§ãªã‘れã°å½ã§ã‚る。新ã—ã„レコードã®å€¤ãŒæ—¢å­˜ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã®æœ€å¤§å€¤ã‚ˆã‚Šå¤§ãã‘れã°ã€æ–°ã—ã„レコードã¯è¿½åŠ ã•れãªã„。新ã—ã„レコードãŒè¿½åŠ ã•れã¦ãƒ¬ã‚³ãƒ¼ãƒ‰æ•°ãŒæœ€å¤§æ•°ã‚’è¶ŠãˆãŸå ´åˆã€æ—¢å­˜ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã®æœ€å¤§å€¤ã®ã‚‚ã®ãŒå‰Šé™¤ã•れる。

ヒープ内ã®ã‚るレコードã®é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’å–å¾—ã™ã‚‹ã«ã¯ã€é–¢æ•° `cbheapget' を用ã„る。

void *cbheapval(CBHEAP *heap, int index);
`heap' ã¯ãƒ’ープãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`index' ã¯å–り出ã™ãƒ¬ã‚³ãƒ¼ãƒ‰ã®ã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹ã‚’指定ã™ã‚‹ã€‚戻り値ã¯è©²å½“レコードã®é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã§ã‚る。`index' ãŒè¦ç´ æ•°ä»¥ä¸Šãªã‚‰ã°ã€æˆ»ã‚Šå€¤ã¯ `NULL' ã§ã‚る。レコードã¯å†…部的ã«ã¯æ¯”較関数ã®è² å€¤ã«åŸºã¥ã„ã¦çµ„織化ã•れã¦ã„ã‚‹ã“ã¨ã«æ³¨æ„ã™ã¹ãã§ã‚る。

ヒープを確ä¿ã•れãŸé ˜åŸŸã«å¤‰æ›ã™ã‚‹ã«ã¯ã€é–¢æ•° `cbheaptomalloc' を用ã„る。

void *cbheaptomalloc(CBHEAP *heap, int *np);
`heap' ã¯ãƒ’ープãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`np' ㌠`NULL' ã§ãªã‘れã°ã€ãã®å‚ç…§å…ˆã«æŠ½å‡ºã—ãŸé ˜åŸŸã®ãƒ¬ã‚³ãƒ¼ãƒ‰æ•°ã‚’æ ¼ç´ã™ã‚‹ã€‚戻り値ã¯ãƒ’ープã®é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã§ã‚る。レコードã¯ã‚½ãƒ¼ãƒˆæ¸ˆã¿ã«ãªã‚‹ã€‚戻り値ã®é ˜åŸŸã¯ `malloc' ã§ç¢ºä¿ã•れるã®ã§ã€ä¸è¦ã«ãªã£ãŸã‚‰ `free' ã§è§£æ”¾ã™ã‚‹ã¹ãã§ã‚る。元ã®ãƒ‡ãƒ¼ã‚¿ã®é ˜åŸŸã¯è§£æ”¾ã•れるã®ã§ã€ãれをå†ã³è§£æ”¾ã—ã¦ã¯ãªã‚‰ãªã„。

書å¼ã«åŸºã¥ã„ãŸæ–‡å­—列をメモリ上ã§ç¢ºä¿ã™ã‚‹ã«ã¯ã€é–¢æ•° `cbsprintf' を用ã„る。

char *cbsprintf(const char *format, ...);
`format' ã¯printfé¢¨ã®æ›¸å¼æ–‡å­—列を指定ã™ã‚‹ã€‚å¤‰æ›æ–‡å­— `%' をフラグ文字 `d'ã€`o'ã€`u'ã€`x'ã€`X'ã€`e'ã€`E'ã€`f'ã€`g'ã€`G'ã€`c'ã€`s' ãŠã‚ˆã³ `%' ã‚’ä¼´ã‚ã›ã¦ä½¿ç”¨ã™ã‚‹ã“ã¨ãŒã§ãる。フィールドã®å¹…ã¨ç²¾åº¦ã®æŒ‡ç¤ºå­ã‚’å¤‰æ›æ–‡å­—ã¨ãƒ•ラグ文字ã®é–“ã«ç½®ãã“ã¨ãŒã§ãる。ãã®æŒ‡ç¤ºå­ã¯10進数字ã€`.'ã€`+'ã€`-' ãŠã‚ˆã³ã‚¹ãƒšãƒ¼ã‚¹æ–‡å­—ã‹ã‚‰ãªã‚‹ã€‚ãã®ä»–ã®å¼•æ•°ã¯æ›¸å¼æ–‡å­—列ã«ã‚ˆã£ã¦åˆ©ç”¨ã•れる。戻り値ã¯çµæžœã®æ–‡å­—列ã®é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã§ã‚る。戻り値ã®é ˜åŸŸã¯ `malloc' ã§ç¢ºä¿ã•れるã®ã§ã€ä¸è¦ã«ãªã£ãŸã‚‰ `free' ã§è§£æ”¾ã™ã‚‹ã¹ãã§ã‚る。

文字列中ã®ãƒ‘ターンを置æ›ã™ã‚‹ã«ã¯ã€é–¢æ•° `cbreplace' を用ã„る。

char *cbreplace(const char *str, CBMAP *pairs);
`str' ã¯ç½®æ›å‰ã®æ–‡å­—列を指定ã™ã‚‹ã€‚`pairs' ã¯ç½®æ›ã®ãƒšã‚¢ã‹ã‚‰ãªã‚‹ãƒžãƒƒãƒ—ã®ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚å„ペアã®ã‚­ãƒ¼ã¯ç½®æ›å‰ã®ãƒ‘ターンを指定ã—ã€å€¤ã¯ç½®æ›å¾Œã®ãƒ‘ターンを指定ã™ã‚‹ã€‚戻り値ã¯çµæžœã®æ–‡å­—列ã®é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã§ã‚る。戻り値ã®é ˜åŸŸã¯ `malloc' ã§ç¢ºä¿ã•れるã®ã§ã€ä¸è¦ã«ãªã£ãŸã‚‰ `free' ã§è§£æ”¾ã™ã‚‹ã¹ãã§ã‚る。

一連ã®ãƒ‡ãƒ¼ã‚¿ã‚’分割ã—ã¦ãƒªã‚¹ãƒˆã‚’作æˆã™ã‚‹ã«ã¯ã€é–¢æ•° `cbsplit' を用ã„る。

CBLIST *cbsplit(const char *ptr, int size, const char *delim);
`ptr' ã¯å†…容ã®é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`size' ã¯ãã®é ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã‹ã€è² æ•°ãªã‚‰ `strlen(ptr)' ã®å€¤ã¨ãªã‚‹ã€‚`delim' ã¯åŒºåˆ‡ã‚Šæ–‡å­—ã‚’å«ã‚€æ–‡å­—列を指定ã™ã‚‹ã‹ã€`NULL' ãªã‚‰çµ‚端文字を区切り文字ã¨ã™ã‚‹ã€‚戻り値ã¯ãƒªã‚¹ãƒˆãƒãƒ³ãƒ‰ãƒ«ã§ã‚る。区切り文字ãŒé€£ç¶šã—ã¦ã„ã‚‹å ´åˆã§ã‚‚ã€ãã®é–“ã«ç©ºã®è¦ç´ ãŒã‚ã‚‹ã¨ã¿ãªã™ã€‚戻り値ã®ãƒãƒ³ãƒ‰ãƒ«ã¯ã€é–¢æ•° `cblistopen' ã§é–‹ã‹ã‚Œã‚‹ã®ã§ã€ä¸è¦ã«ãªã£ãŸã‚‰ `cblistclose' ã§é–‰ã˜ã‚‹ã¹ãã§ã‚る。

ファイルã®å…¨ãƒ‡ãƒ¼ã‚¿ã‚’読ã¿è¾¼ã‚€ã«ã¯ã€é–¢æ•° `cbreadfile' を用ã„る。

char *cbreadfile(const char *name, int *sp);
`name' ã¯ãƒ•ァイルã®åå‰ã‚’指定ã™ã‚‹ãŒã€`NULL' ãªã‚‰æ¨™æº–入力を読ã¿è¾¼ã‚€ã€‚`sp' ㌠`NULL' ã§ãªã‘れã°ã€ãã®å‚ç…§å…ˆã«æŠ½å‡ºã—ãŸé ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’æ ¼ç´ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰èª­ã¿è¾¼ã‚“ã ãƒ‡ãƒ¼ã‚¿ã‚’æ ¼ç´ã—ãŸé ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰ `NULL' ã§ã‚る。戻り値ã®é ˜åŸŸã¯ã€å®Ÿéš›ã«ã¯1ãƒã‚¤ãƒˆå¤šã確ä¿ã—ã¦çµ‚端文字ãŒç½®ã‹ã‚Œã‚‹ã®ã§ã€æ–‡å­—列ã¨ã—ã¦åˆ©ç”¨ã§ãる。戻り値ã®é ˜åŸŸã¯ `malloc' ã§ç¢ºä¿ã•れるã®ã§ã€ä¸è¦ã«ãªã£ãŸã‚‰ `free' ã§è§£æ”¾ã™ã‚‹ã¹ãã§ã‚る。

一連ã®ãƒ‡ãƒ¼ã‚¿ã‚’ãƒ•ã‚¡ã‚¤ãƒ«ã«æ›¸ã込むã«ã¯ã€é–¢æ•° `cbwritefile' を用ã„る。

int cbwritefile(const char *name, const char *ptr, int size);
`name' ã¯ãƒ•ァイルåを指定ã™ã‚‹ãŒã€`NULL' ãªã‚‰æ¨™æº–å‡ºåŠ›ã«æ›¸ã出ã•れる。`size' ã¯ãã®é ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã‹ã€è² æ•°ãªã‚‰ `strlen(ptr)' ã®å€¤ã¨ãªã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰çœŸã§ã‚りã€è©²å½“ã®ã‚¨ãƒ©ãƒ¼ãªã‚‰å½ã§ã‚る。ファイルãŒå­˜åœ¨ã™ã‚‹å ´åˆã«ã¯ä¸Šæ›¸ãã•れã€ãã†ã§ãªã„å ´åˆã¯æ–°ã—ã„ファイルãŒç”Ÿæˆã•れる。

ファイルã®å„行を読ã¿è¾¼ã‚€ã«ã¯ã€é–¢æ•° `cbreadlines' を用ã„る。

CBLIST *cbreadlines(const char *name);
`name' ã¯ãƒ•ァイルã®åå‰ã‚’指定ã™ã‚‹ãŒã€`NULL' ãªã‚‰æ¨™æº–入力を読ã¿è¾¼ã‚€ã€‚æˆåŠŸã™ã‚Œã°æˆ»ã‚Šå€¤ã¯å„行ã®ãƒ‡ãƒ¼ã‚¿ã‚’ä¿æŒã™ã‚‹ãƒªã‚¹ãƒˆã®ãƒãƒ³ãƒ‰ãƒ«ã§ã‚りã€å¤±æ•—ãªã‚‰ `NULL' ã§ã‚る。改行文字ã¯å‰Šé™¤ã•れる。戻り値ã®ãƒãƒ³ãƒ‰ãƒ«ã¯é–¢æ•° `cblistopen' ã§é–‹ã‹ã‚Œã‚‹ã®ã§ã€ä¸è¦ã«ãªã£ãŸã‚‰ `cblistclose' ã§é–‰ã˜ã‚‹ã¹ãã§ã‚る。

ディレクトリã«å«ã¾ã‚Œã‚‹ãƒ•ァイルã®åå‰ã®ãƒªã‚¹ãƒˆã‚’å¾—ã‚‹ã«ã¯ã€é–¢æ•° `cbdirlist' を用ã„る。

CBLIST *cbdirlist(const char *name);
`name' ã¯ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã®åå‰ã‚’指定ã™ã‚‹ã€‚æˆåŠŸã™ã‚Œã°æˆ»ã‚Šå€¤ã¯å„ファイルã®åå‰ã‚’ä¿æŒã™ã‚‹ãƒªã‚¹ãƒˆã®ãƒãƒ³ãƒ‰ãƒ«ã§ã‚りã€å¤±æ•—ãªã‚‰ `NULL' ã§ã‚る。戻り値ã®ãƒãƒ³ãƒ‰ãƒ«ã¯é–¢æ•° `cblistopen' ã§é–‹ã‹ã‚Œã‚‹ã®ã§ã€ä¸è¦ã«ãªã£ãŸã‚‰ `cblistclose' ã§é–‰ã˜ã‚‹ã¹ãã§ã‚る。

ファイルやディレクトリã®çŠ¶æ…‹ã‚’å¾—ã‚‹ã«ã¯ã€é–¢æ•° `cbfilestat' を用ã„る。

int cbfilestat(const char *name, int *isdirp, int *sizep, int *mtimep);
`name' ã¯ãƒ•ァイルやディレクトリã®åå‰ã‚’指定ã™ã‚‹ã€‚`dirp' ㌠`NULL' ã§ãªã‘れã°ã€ãã®å‚ç…§å…ˆã«ãƒ•ァイルãŒãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã‹å¦ã‹ã‚’æ ¼ç´ã™ã‚‹ã€‚`sizep' ㌠`NULL' ã§ãªã‘れã°ã€ãã®å‚ç…§å…ˆã«ãƒ•ァイルã®ã‚µã‚¤ã‚ºã‚’æ ¼ç´ã™ã‚‹ã€‚`mtimep' ㌠`NULL' ã§ãªã‘れã°ã€ãã®å‚ç…§å…ˆã«ãƒ•ã‚¡ã‚¤ãƒ«ã®æœ€çµ‚更新時刻を格ç´ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰çœŸã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰å½ã§ã‚る。ファイルãŒå­˜åœ¨ã—ãªã„å ´åˆã‚„パーミッションãŒãªã„å ´åˆã‚‚å½ã‚’è¿”ã™ã€‚

ファイルã‹ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã¨ãã®å†…容を削除ã™ã‚‹ã«ã¯ã€é–¢æ•° `cbremove' を用ã„る。

int cbremove(const char *name);
`name' ã¯ãƒ•ァイルやディレクトリã®åå‰ã‚’指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰çœŸã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰å½ã§ã‚る。ファイルãŒå­˜åœ¨ã—ãªã„å ´åˆã‚„パーミッションãŒãªã„å ´åˆã‚‚å½ã‚’è¿”ã™ã€‚

URLã‚’æ§‹æˆè¦ç´ ã«åˆ†è§£ã™ã‚‹ã«ã¯ã€é–¢æ•° `cburlbreak' を用ã„る。

CBMAP *cburlbreak(const char *str);
`str' ã¯URLã®æ–‡å­—列ã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚戻り値ã¯ãƒžãƒƒãƒ—ãƒãƒ³ãƒ‰ãƒ«ã§ã‚る。マップã®å„キーã¯è¦ç´ åã§ã‚る。キー "self" ã¯URLãれ自体を指示ã™ã‚‹ã€‚キー "scheme" ã¯URLã®ã‚¹ã‚­ãƒ¼ãƒ ã‚’指示ã™ã‚‹ã€‚キー "host" ã¯ã‚µãƒ¼ãƒã®ãƒ›ã‚¹ãƒˆåを指示ã™ã‚‹ã€‚キー "port" ã¯ã‚µãƒ¼ãƒã®ãƒãƒ¼ãƒˆç•ªå·ã‚’指示ã™ã‚‹ã€‚キー "authority" ã¯èªè¨¼æƒ…報を指示ã™ã‚‹ã€‚キー "path" ã¯ãƒªã‚½ãƒ¼ã‚¹ã®ãƒ‘スを指示ã™ã‚‹ã€‚キー "file" ã¯ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªéƒ¨åˆ†ã‚’除ã„ãŸãƒ•ァイルåを指示ã™ã‚‹ã€‚キー "query" ã¯ã‚¯ã‚¨ãƒªæ–‡å­—列を指示ã™ã‚‹ã€‚キー "fragment" ã¯ãƒ•ラグメント文字列を指示ã™ã‚‹ã€‚サãƒãƒ¼ãƒˆã•れるスキームã¯HTTPã¨HTTPSã¨FTPã¨FILEã§ã‚る。絶対URLã«ã‚‚相対URLã«ã‚‚対応ã™ã‚‹ã€‚戻り値ã®ãƒãƒ³ãƒ‰ãƒ«ã¯é–¢æ•° `cbmapopen' ã§é–‹ã‹ã‚Œã‚‹ã®ã§ã€ä¸è¦ã«ãªã£ãŸã‚‰ `cbmapclose' ã§é–‰ã˜ã‚‹ã¹ãã§ã‚る。

相対URLを絶対URLを用ã„ã¦è§£æ±ºã™ã‚‹ã«ã¯ã€é–¢æ•° `cburlresolve' を用ã„る。

char *cburlresolve(const char *base, const char *target);
`base' ã¯ãƒ™ãƒ¼ã‚¹ãƒ­ã‚±ãƒ¼ã‚·ãƒ§ãƒ³ã®çµ¶å¯¾URLを指定ã™ã‚‹ã€‚`target' ã¯è§£æ±ºã™ã¹ãURLを指定ã™ã‚‹ã€‚戻り値ã¯è§£æ±ºã•れãŸURLã§ã‚る。ターゲットURLãŒç›¸å¯¾URLã®å ´åˆã€ãƒ™ãƒ¼ã‚¹ãƒ­ã‚±ãƒ¼ã‚·ãƒ§ãƒ³ã‹ã‚‰ã®ç›¸å¯¾ä½ç½®ã®URLã‚’è¿”ã™ã€‚ターゲットURLãŒçµ¶å¯¾URLã®å ´åˆã€ã‚¿ãƒ¼ã‚²ãƒƒãƒˆURLã®ã‚³ãƒ”ーを返ã™ã€‚戻り値ã®é ˜åŸŸã¯ `malloc' ã§ç¢ºä¿ã•れるã®ã§ã€ä¸è¦ã«ãªã£ãŸã‚‰ `free' ã§è§£æ”¾ã™ã‚‹ã¹ãã§ã‚る。

一連ã®ã‚ªãƒ–ジェクトをURLエンコーディングã§ç¬¦å·åŒ–ã™ã‚‹ã«ã¯ã€é–¢æ•° `cburlencode' を用ã„る。

char *cburlencode(const char *ptr, int size);
`ptr' ã¯é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`size' ã¯ãã®é ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã‹ã€è² æ•°ãªã‚‰ `strlen(ptr)' ã®å€¤ã¨ãªã‚‹ã€‚戻り値ã¯çµæžœã®æ–‡å­—列ã¸ã®ãƒã‚¤ãƒ³ã‚¿ã§ã‚る。戻り値ã®é ˜åŸŸã¯ `malloc' ã§ç¢ºä¿ã•れるã®ã§ã€ä¸è¦ã«ãªã£ãŸã‚‰ `free' ã§è§£æ”¾ã™ã‚‹ã¹ãã§ã‚る。

URLエンコーディングã§ç¬¦å·åŒ–ã•ã‚ŒãŸæ–‡å­—列を復元ã™ã‚‹ã«ã¯ã€é–¢æ•° `cburldecode' を用ã„る。

char *cburldecode(const char *str, int *sp);
`str' ã¯ç¬¦å·åŒ–ã•ã‚ŒãŸæ–‡å­—列ã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`sp' ㌠`NULL' ã§ãªã‘れã°ã€ãã®å‚ç…§å…ˆã«æŠ½å‡ºã—ãŸé ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’æ ¼ç´ã™ã‚‹ã€‚戻り値ã¯çµæžœã®é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã§ã‚る。戻り値ã®é ˜åŸŸã¯ã€å®Ÿéš›ã«ã¯1ãƒã‚¤ãƒˆå¤šã確ä¿ã—ã¦çµ‚端文字ãŒç½®ã‹ã‚Œã‚‹ã®ã§ã€æ–‡å­—列ã¨ã—ã¦åˆ©ç”¨ã§ãる。戻り値ã®é ˜åŸŸã¯ `malloc' ã§ç¢ºä¿ã•れるã®ã§ã€ä¸è¦ã«ãªã£ãŸã‚‰ `free' ã§è§£æ”¾ã™ã‚‹ã¹ãã§ã‚る。

一連ã®ã‚ªãƒ–ジェクトをBase64エンコーディングã§ç¬¦å·åŒ–ã™ã‚‹ã«ã¯ã€é–¢æ•° `cbbaseencode' を用ã„る。

char *cbbaseencode(const char *ptr, int size);
`ptr' ã¯é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`size' ã¯ãã®é ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã‹ã€è² æ•°ãªã‚‰ `strlen(ptr)' ã®å€¤ã¨ãªã‚‹ã€‚戻り値ã¯çµæžœã®æ–‡å­—列ã¸ã®ãƒã‚¤ãƒ³ã‚¿ã§ã‚る。戻り値ã®é ˜åŸŸã¯ `malloc' ã§ç¢ºä¿ã•れるã®ã§ã€ä¸è¦ã«ãªã£ãŸã‚‰ `free' ã§è§£æ”¾ã™ã‚‹ã¹ãã§ã‚る。

Base64エンコーディングã§ç¬¦å·åŒ–ã•ã‚ŒãŸæ–‡å­—列を復元ã™ã‚‹ã«ã¯ã€é–¢æ•° `cbbasedecode' を用ã„る。

char *cbbasedecode(const char *str, int *sp);
`str' ã¯ç¬¦å·åŒ–ã•ã‚ŒãŸæ–‡å­—列ã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`sp' ㌠`NULL' ã§ãªã‘れã°ã€ãã®å‚ç…§å…ˆã«æŠ½å‡ºã—ãŸé ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’æ ¼ç´ã™ã‚‹ã€‚戻り値ã¯çµæžœã®é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã§ã‚る。戻り値ã®é ˜åŸŸã¯ã€å®Ÿéš›ã«ã¯1ãƒã‚¤ãƒˆå¤šã確ä¿ã—ã¦çµ‚端文字ãŒç½®ã‹ã‚Œã‚‹ã®ã§ã€æ–‡å­—列ã¨ã—ã¦åˆ©ç”¨ã§ãる。戻り値ã®é ˜åŸŸã¯ `malloc' ã§ç¢ºä¿ã•れるã®ã§ã€ä¸è¦ã«ãªã£ãŸã‚‰ `free' ã§è§£æ”¾ã™ã‚‹ã¹ãã§ã‚る。

一連ã®ã‚ªãƒ–ジェクトをquoted-printableエンコーディングã§ç¬¦å·åŒ–ã™ã‚‹ã«ã¯ã€é–¢æ•° `cbquoteencode' を用ã„る。

char *cbquoteencode(const char *ptr, int size);
`ptr' ã¯é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`size' ã¯ãã®é ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã‹ã€è² æ•°ãªã‚‰ `strlen(ptr)' ã®å€¤ã¨ãªã‚‹ã€‚戻り値ã¯çµæžœã®æ–‡å­—列ã¸ã®ãƒã‚¤ãƒ³ã‚¿ã§ã‚る。戻り値ã®é ˜åŸŸã¯ `malloc' ã§ç¢ºä¿ã•れるã®ã§ã€ä¸è¦ã«ãªã£ãŸã‚‰ `free' ã§è§£æ”¾ã™ã‚‹ã¹ãã§ã‚る。

quoted-printableエンコーディングã§ç¬¦å·åŒ–ã•ã‚ŒãŸæ–‡å­—列を復元ã™ã‚‹ã«ã¯ã€é–¢æ•° `cbquotedecode' を用ã„る。

char *cbquotedecode(const char *str, int *sp);
`str' ã¯ç¬¦å·åŒ–ã•ã‚ŒãŸæ–‡å­—列ã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`sp' ㌠`NULL' ã§ãªã‘れã°ã€ãã®å‚ç…§å…ˆã«æŠ½å‡ºã—ãŸé ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’æ ¼ç´ã™ã‚‹ã€‚戻り値ã¯çµæžœã®é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã§ã‚る。戻り値ã®é ˜åŸŸã¯ã€å®Ÿéš›ã«ã¯1ãƒã‚¤ãƒˆå¤šã確ä¿ã—ã¦çµ‚端文字ãŒç½®ã‹ã‚Œã‚‹ã®ã§ã€æ–‡å­—列ã¨ã—ã¦åˆ©ç”¨ã§ãる。戻り値ã®é ˜åŸŸã¯ `malloc' ã§ç¢ºä¿ã•れるã®ã§ã€ä¸è¦ã«ãªã£ãŸã‚‰ `free' ã§è§£æ”¾ã™ã‚‹ã¹ãã§ã‚る。

MIMEã®æ–‡å­—列をヘッダã¨ãƒœãƒ‡ã‚£ã«åˆ†å‰²ã™ã‚‹ã«ã¯ã€é–¢æ•° `cbmimebreak' を用ã„る。

char *cbmimebreak(const char *ptr, int size, CBMAP *attrs, int *sp);
`ptr' ã¯MIMEã®ãƒ‡ãƒ¼ã‚¿ã®é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`size' ã¯ãã®é ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã‹ã€è² æ•°ãªã‚‰ `strlen(ptr)' ã®å€¤ã¨ãªã‚‹ã€‚`attrs' ã¯å±žæ€§ã‚’ä¿å­˜ã™ã‚‹ãŸã‚ã®ãƒžãƒƒãƒ—ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ãŒã€`NULL' ã®å ´åˆã«ã¯åˆ©ç”¨ã•れãªã„。マップã®å„キーã¯å°æ–‡å­—ã«æ­£è¦åŒ–ã•れãŸå±žæ€§åã§ã‚る。`sp' ㌠`NULL' ã§ãªã‘れã°ã€ãã®å‚ç…§å…ˆã«æŠ½å‡ºã—ãŸé ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’æ ¼ç´ã™ã‚‹ã€‚戻り値ã¯ãƒœãƒ‡ã‚£ã®æ–‡å­—列ã§ã‚ã‚‹ã€‚ã‚³ãƒ³ãƒ†ãƒ³ãƒˆã‚¿ã‚¤ãƒ—ãŒæŒ‡å®šã•れã¦ã„ã‚‹å ´åˆã€ãƒžãƒƒãƒ—ã®ã‚­ãƒ¼ "TYPE" ã¯ãã®ã‚¿ã‚¤ãƒ—を指示ã™ã‚‹ã€‚æ–‡å­—ã‚³ãƒ¼ãƒ‰ãŒæŒ‡å®šã•れã¦ã„ã‚‹å ´åˆã€ã‚­ãƒ¼ "CHARSET" ã¯ãã®ã‚³ãƒ¼ãƒ‰åを指示ã™ã‚‹ã€‚マルãƒãƒ‘ートã®åŒºåˆ‡ã‚Šæ–‡å­—åˆ—ãŒæŒ‡å®šã•れã¦ã„ã‚‹å ´åˆã€ã‚­ãƒ¼ "BOUNDARY" ã¯ãã®æ–‡å­—列を指示ã™ã‚‹ã€‚コンテントディスãƒã‚¸ã‚·ãƒ§ãƒ³ãŒæŒ‡å®šã•れã¦ã„ã‚‹å ´åˆã€ã‚­ãƒ¼ "DISPOSITION" ã¯ãã®æ–¹é‡ã‚’指示ã™ã‚‹ã€‚ファイルåãŒæŒ‡å®šã•れã¦ã„ã‚‹å ´åˆã€ã‚­ãƒ¼ "FILENAME" ã¯ãã®åå‰ã‚’指示ã™ã‚‹ã€‚属性åãŒæŒ‡å®šã•れã¦ã„ã‚‹å ´åˆã€ã‚­ãƒ¼ "NAME" ã¯ãã®åå‰ã‚’指示ã™ã‚‹ã€‚戻り値ã®é ˜åŸŸã¯ `malloc' ã§ç¢ºä¿ã•れるã®ã§ã€ä¸è¦ã«ãªã£ãŸã‚‰ `free' ã§è§£æ”¾ã™ã‚‹ã¹ãã§ã‚る。

MIMEã®ãƒžãƒ«ãƒãƒ‘ãƒ¼ãƒˆãƒ‡ãƒ¼ã‚¿ã®æ–‡å­—列をå„パートã«åˆ†å‰²ã™ã‚‹ã«ã¯ã€é–¢æ•° `cbmimeparts' を用ã„る。

CBLIST *cbmimeparts(const char *ptr, int size, const char *boundary);
`ptr' ã¯MIMEã®ãƒ‡ãƒ¼ã‚¿ã®é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`size' ã¯ãã®é ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã‹ã€è² æ•°ãªã‚‰ `strlen(ptr)' ã®å€¤ã¨ãªã‚‹ã€‚`boundary' ã¯åŒºåˆ‡ã‚Šæ–‡å­—列ã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚戻り値ã¯ãƒªã‚¹ãƒˆãƒãƒ³ãƒ‰ãƒ«ã§ã‚る。リストã®å„è¦ç´ ã¯ãƒ‘ãƒ¼ãƒˆã®æ–‡å­—列ã§ã‚る。戻り値ã®ãƒãƒ³ãƒ‰ãƒ«ã¯é–¢æ•° `cblistopen' ã§é–‹ã‹ã‚Œã‚‹ã®ã§ã€ä¸è¦ã«ãªã£ãŸã‚‰ `cblistclose' ã§é–‰ã˜ã‚‹ã¹ãã§ã‚る。

文字列をMIMEエンコーディングã§ç¬¦å·åŒ–ã™ã‚‹ã«ã¯ã€é–¢æ•° `cbmimeencode' を用ã„る。

char *cbmimeencode(const char *str, const char *encname, int base);
`str' ã¯æ–‡å­—列ã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`encname' ã¯æ–‡å­—コードåã®æ–‡å­—列を指定ã™ã‚‹ã€‚`base' ã¯Base64エンコードを使ã†ã‹å¦ã‹ã‚’指定ã™ã‚‹ã€‚å½ã®å ´åˆã¯quoted-printableãŒç”¨ã„られる。戻り値ã¯çµæžœã®æ–‡å­—列ã¸ã®ãƒã‚¤ãƒ³ã‚¿ã§ã‚る。戻り値ã®é ˜åŸŸã¯ `malloc' ã§ç¢ºä¿ã•れるã®ã§ã€ä¸è¦ã«ãªã£ãŸã‚‰ `free' ã§è§£æ”¾ã™ã‚‹ã¹ãã§ã‚る。

MIMEエンコーディングã§ç¬¦å·åŒ–ã•ã‚ŒãŸæ–‡å­—列を復元ã™ã‚‹ã«ã¯ã€é–¢æ•° `cbmimedecode' を用ã„る。

char *cbmimedecode(const char *str, char *enp);
`str' ã¯ç¬¦å·åŒ–ã•ã‚ŒãŸæ–‡å­—列ã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`enp' ã¯æ–‡å­—コードåを書ã込むãŸã‚ã®é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ãŒã€`NULL' ã®å ´åˆã¯åˆ©ç”¨ã•れãªã„。ãƒãƒƒãƒ•ã‚¡ã®ã‚µã‚¤ã‚ºã¯32ãƒã‚¤ãƒˆä»¥ä¸Šã§ãªã‘れã°ãªã‚‰ãªã„。戻り値ã¯çµæžœã®æ–‡å­—列ã¸ã®ãƒã‚¤ãƒ³ã‚¿ã§ã‚る。戻り値ã®é ˜åŸŸã¯ `malloc' ã§ç¢ºä¿ã•れるã®ã§ã€ä¸è¦ã«ãªã£ãŸã‚‰ `free' ã§è§£æ”¾ã™ã‚‹ã¹ãã§ã‚る。

CSVã®æ–‡å­—列を行ã«åˆ†å‰²ã™ã‚‹ã«ã¯ã€é–¢æ•° `cbcsvrows' を用ã„る。

CBLIST *cbcsvrows(const char *str);
`str' ã¯CSVã®æ–‡å­—列ã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚戻り値ã¯ãƒªã‚¹ãƒˆãƒãƒ³ãƒ‰ãƒ«ã§ã‚る。リストã®å„è¦ç´ ã¯è¡Œã®æ–‡å­—列ã§ã‚る。戻り値ã®ãƒãƒ³ãƒ‰ãƒ«ã¯é–¢æ•° `cblistopen' ã§é–‹ã‹ã‚Œã‚‹ã®ã§ã€ä¸è¦ã«ãªã£ãŸã‚‰ `cblistclose' ã§é–‰ã˜ã‚‹ã¹ãã§ã‚ã‚‹ã€‚å…¥åŠ›æ–‡å­—åˆ—ã®æ–‡å­—コードã¯US-ASCIIã€UTF-8ã€ISO-8859-*ã€EUC-*ã€Shift_JISã®ã©ã‚Œã‹ã§ã‚ã‚‹å¿…è¦ãŒã‚る。MS-Excelã¨äº’æ›ã—ã¦ã€ã“れらCSV用関数群ã¯ã€ãƒ€ãƒ–ルクォートã§å›²ã‚“ã§ã‚³ãƒ³ãƒžãªã©ã®ãƒ¡ã‚¿æ–‡å­—ã‚’å«ã‚ãŸã‚»ãƒ«ã‚’扱ã†ã“ã¨ãŒã§ãる。

CSVã®è¡Œã®æ–‡å­—列をセルã«åˆ†å‰²ã™ã‚‹ã«ã¯ã€é–¢æ•° `cbcsvcells' を用ã„る。

CBLIST *cbcsvcells(const char *str);
`str' ã¯CSVã®è¡Œã®æ–‡å­—列ã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚戻り値ã¯ãƒªã‚¹ãƒˆãƒãƒ³ãƒ‰ãƒ«ã§ã‚る。リストã®å„è¦ç´ ã¯ã‚»ãƒ«å†…容をアンエスケープã—ãŸæ–‡å­—列ã§ã‚る。戻り値ã®ãƒãƒ³ãƒ‰ãƒ«ã¯é–¢æ•° `cblistopen' ã§é–‹ã‹ã‚Œã‚‹ã®ã§ã€ä¸è¦ã«ãªã£ãŸã‚‰ `cblistclose' ã§é–‰ã˜ã‚‹ã¹ãã§ã‚る。

CSVã®ãƒ¡ã‚¿æ–‡å­—をエスケープã—ãŸæ–‡å­—列を得るã«ã¯ã€é–¢æ•° `cbcsvescape' を用ã„る。

char *cbcsvescape(const char *str);
`str' ã¯å¯¾è±¡ã®æ–‡å­—列ã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚戻り値ã¯ãƒ¡ã‚¿æ–‡å­—を無効化ã—ãŸçµæžœã®æ–‡å­—列ã¸ã®ãƒã‚¤ãƒ³ã‚¿ã§ã‚る。戻り値ã®é ˜åŸŸã¯ `malloc' ã§ç¢ºä¿ã•れるã®ã§ã€ä¸è¦ã«ãªã£ãŸã‚‰ `free' ã§è§£æ”¾ã™ã‚‹ã¹ãã§ã‚る。

XMLã®å®Ÿä½“å‚照をアンエスケープã—ãŸæ–‡å­—列を得るã«ã¯ã€é–¢æ•° `cbcsvunescape' を用ã„る。

char *cbcsvunescape(const char *str);
`str' ã¯å¯¾è±¡ã®æ–‡å­—列ã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚戻り値ã¯ãƒ¡ã‚¿æ–‡å­—ã‚’ä¼´ã£ãŸçµæžœã®æ–‡å­—列ã¸ã®ãƒã‚¤ãƒ³ã‚¿ã§ã‚る。戻り値ã®é ˜åŸŸã¯ `malloc' ã§ç¢ºä¿ã•れるã®ã§ã€ä¸è¦ã«ãªã£ãŸã‚‰ `free' ã§è§£æ”¾ã™ã‚‹ã¹ãã§ã‚る。

XMLã®æ–‡å­—列をタグã¨ãƒ†ã‚­ã‚¹ãƒˆã‚»ã‚¯ã‚·ãƒ§ãƒ³ã«åˆ†å‰²ã™ã‚‹ã«ã¯ã€é–¢æ•° `cbxmlbreak' を用ã„る。

CBLIST *cbxmlbreak(const char *str, int cr);
`str' ã¯XMLã®æ–‡å­—列ã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`cr' ã¯ã‚³ãƒ¡ãƒ³ãƒˆã‚’削除ã™ã‚‹ã‹å¦ã‹ã‚’指定ã™ã‚‹ã€‚戻り値ã¯ãƒªã‚¹ãƒˆãƒãƒ³ãƒ‰ãƒ«ã§ã‚る。リストã®å„è¦ç´ ã¯ã‚¿ã‚°ã‹ãƒ†ã‚­ã‚¹ãƒˆã‚»ã‚¯ã‚·ãƒ§ãƒ³ã®æ–‡å­—列ã§ã‚る。戻り値ã®ãƒãƒ³ãƒ‰ãƒ«ã¯é–¢æ•° `cblistopen' ã§é–‹ã‹ã‚Œã‚‹ã®ã§ã€ä¸è¦ã«ãªã£ãŸã‚‰ `cblistclose' ã§é–‰ã˜ã‚‹ã¹ãã§ã‚ã‚‹ã€‚å…¥åŠ›æ–‡å­—åˆ—ã®æ–‡å­—コードã¯US-ASCIIã€UTF-8ã€ISO-8859-*ã€EUC-*ã€Shift_JISã®ã©ã‚Œã‹ã§ã‚ã‚‹å¿…è¦ãŒã‚る。ã“れらXML用関数群ã¯å¦¥å½“性検証を行ã†XMLパーザã§ã¯ãªã„ã®ã§ã€HTMLã‚„SGMLも扱ã†ã“ã¨ãŒã§ãる。

XMLã®ã‚¿ã‚°ã®å±žæ€§ã®ãƒžãƒƒãƒ—ã‚’å¾—ã‚‹ã«ã¯ã€é–¢æ•° `cbxmlattrs' を用ã„る。

CBMAP *cbxmlattrs(const char *str);
`str' ã¯ã‚¿ã‚°ã®æ–‡å­—列ã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚戻り値ã¯ãƒžãƒƒãƒ—ãƒãƒ³ãƒ‰ãƒ«ã§ã‚る。マップã®å„キーã¯å±žæ€§ã®åå‰ã§ã‚る。å„値ã¯ã‚¢ãƒ³ã‚¨ã‚¹ã‚±ãƒ¼ãƒ—ã•れる。空文字列をキーã«ã™ã‚‹ã¨ã‚¿ã‚°ã®åå‰ã‚’å–り出ã™ã“ã¨ãŒã§ãる。戻り値ã®ãƒãƒ³ãƒ‰ãƒ«ã¯é–¢æ•° `cbmapopen' ã§é–‹ã‹ã‚Œã‚‹ã®ã§ã€ä¸è¦ã«ãªã£ãŸã‚‰ `cbmapclose' ã§é–‰ã˜ã‚‹ã¹ãã§ã‚る。

XMLã®ãƒ¡ã‚¿æ–‡å­—をエスケープã—ãŸæ–‡å­—列を得るã«ã¯ã€é–¢æ•° `cbxmlescape' を用ã„る。

char *cbxmlescape(const char *str);
`str' ã¯å¯¾è±¡ã®æ–‡å­—列ã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚戻り値ã¯ãƒ¡ã‚¿æ–‡å­—を無効化ã—ãŸçµæžœã®æ–‡å­—列ã¸ã®ãƒã‚¤ãƒ³ã‚¿ã§ã‚る。ã“ã®é–¢æ•°ã¯ `&'〠`<'ã€`>'ã€`"' ã®ã¿ã‚’変æ›ã™ã‚‹ã€‚戻り値ã®é ˜åŸŸã¯ `malloc' ã§ç¢ºä¿ã•れるã®ã§ã€ä¸è¦ã«ãªã£ãŸã‚‰ `free' ã§è§£æ”¾ã™ã‚‹ã¹ãã§ã‚る。

XMLã®å®Ÿä½“å‚照をアンエスケープã—ãŸæ–‡å­—列を得るã«ã¯ã€é–¢æ•° `cbxmlunescape' を用ã„る。

char *cbxmlunescape(const char *str);
`str' ã¯å¯¾è±¡ã®æ–‡å­—列ã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚戻り値ã¯ãƒ¡ã‚¿æ–‡å­—ã‚’ä¼´ã£ãŸçµæžœã®æ–‡å­—列ã¸ã®ãƒã‚¤ãƒ³ã‚¿ã§ã‚る。ã“ã®é–¢æ•°ã¯ `&amp;'ã€`&lt;'ã€`&gt;'ã€`&quot;' ã®ã¿ã‚’復元ã™ã‚‹ã€‚戻り値ã®é ˜åŸŸã¯ `malloc' ã§ç¢ºä¿ã•れるã®ã§ã€ä¸è¦ã«ãªã£ãŸã‚‰ `free' ã§è§£æ”¾ã™ã‚‹ã¹ãã§ã‚る。

ZLIBを用ã„ã¦ä¸€é€£ã®ã‚ªãƒ–ジェクトを圧縮ã™ã‚‹ã«ã¯ã€é–¢æ•° `cbdeflate' を用ã„る。

char *cbdeflate(const char *ptr, int size, int *sp);
`ptr' ã¯é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`size' ã¯ãã®é ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã‹ã€è² æ•°ãªã‚‰ `strlen(ptr)' ã®å€¤ã¨ãªã‚‹ã€‚`sp' ã®å‚ç…§å…ˆã«ã¯æŠ½å‡ºã—ãŸé ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’æ ¼ç´ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰çµæžœã®é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰ `NULL' ã§ã‚る。戻り値ã®é ˜åŸŸã¯ `malloc' ã§ç¢ºä¿ã•れるã®ã§ã€ä¸è¦ã«ãªã£ãŸã‚‰ `free' ã§è§£æ”¾ã™ã‚‹ã¹ãã§ã‚る。ã“ã®é–¢æ•°ã¯QDBMãŒZLIBを有効ã«ã—ã¦ãƒ“ルドã•れãŸå ´åˆã®ã¿åˆ©ç”¨ã§ãる。

ZLIBを用ã„ã¦åœ§ç¸®ã•れãŸã‚ªãƒ–ジェクトを伸長ã™ã‚‹ã«ã¯ã€é–¢æ•° `cbinflate' を用ã„る。

char *cbinflate(const char *ptr, int size, int *sp);
`ptr' ã¯é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`sp' ㌠`NULL' ã§ãªã‘れã°ã€ãã®å‚ç…§å…ˆã«æŠ½å‡ºã—ãŸé ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’æ ¼ç´ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰çµæžœã®é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰ `NULL' ã§ã‚る。戻り値ã®é ˜åŸŸã¯ã€å®Ÿéš›ã«ã¯1ãƒã‚¤ãƒˆå¤šã確ä¿ã—ã¦çµ‚端文字ãŒç½®ã‹ã‚Œã‚‹ã®ã§ã€æ–‡å­—列ã¨ã—ã¦åˆ©ç”¨ã§ãる。戻り値ã®é ˜åŸŸã¯ `malloc' ã§ç¢ºä¿ã•れるã®ã§ã€ä¸è¦ã«ãªã£ãŸã‚‰ `free' ã§è§£æ”¾ã™ã‚‹ã¹ãã§ã‚る。ã“ã®é–¢æ•°ã¯QDBMãŒZLIBを有効ã«ã—ã¦ãƒ“ルドã•れãŸå ´åˆã®ã¿åˆ©ç”¨ã§ãる。

GZIPを用ã„ã¦ä¸€é€£ã®ã‚ªãƒ–ジェクトを圧縮ã™ã‚‹ã«ã¯ã€é–¢æ•° `cbgzencode' を用ã„る。

char *cbgzencode(const char *ptr, int size, int *sp);
`ptr' ã¯é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`size' ã¯ãã®é ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã‹ã€è² æ•°ãªã‚‰ `strlen(ptr)' ã®å€¤ã¨ãªã‚‹ã€‚`sp' ã®å‚ç…§å…ˆã«ã¯æŠ½å‡ºã—ãŸé ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’æ ¼ç´ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰çµæžœã®é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰ `NULL' ã§ã‚る。戻り値ã®é ˜åŸŸã¯ `malloc' ã§ç¢ºä¿ã•れるã®ã§ã€ä¸è¦ã«ãªã£ãŸã‚‰ `free' ã§è§£æ”¾ã™ã‚‹ã¹ãã§ã‚る。ã“ã®é–¢æ•°ã¯QDBMãŒZLIBを有効ã«ã—ã¦ãƒ“ルドã•れãŸå ´åˆã®ã¿åˆ©ç”¨ã§ãる。

GZIPを用ã„ã¦åœ§ç¸®ã•れãŸã‚ªãƒ–ジェクトを伸長ã™ã‚‹ã«ã¯ã€é–¢æ•° `cbgzdecode' を用ã„る。

char *cbgzdecode(const char *ptr, int size, int *sp);
`ptr' ã¯é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`sp' ㌠`NULL' ã§ãªã‘れã°ã€ãã®å‚ç…§å…ˆã«æŠ½å‡ºã—ãŸé ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’æ ¼ç´ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰çµæžœã®é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰ `NULL' ã§ã‚る。戻り値ã®é ˜åŸŸã¯ã€å®Ÿéš›ã«ã¯1ãƒã‚¤ãƒˆå¤šã確ä¿ã—ã¦çµ‚端文字ãŒç½®ã‹ã‚Œã‚‹ã®ã§ã€æ–‡å­—列ã¨ã—ã¦åˆ©ç”¨ã§ãる。戻り値ã®é ˜åŸŸã¯ `malloc' ã§ç¢ºä¿ã•れるã®ã§ã€ä¸è¦ã«ãªã£ãŸã‚‰ `free' ã§è§£æ”¾ã™ã‚‹ã¹ãã§ã‚る。ã“ã®é–¢æ•°ã¯QDBMãŒZLIBを有効ã«ã—ã¦ãƒ“ルドã•れãŸå ´åˆã®ã¿åˆ©ç”¨ã§ãる。

一連ã®ã‚ªãƒ–ジェクトã®CRC32ãƒã‚§ãƒƒã‚¯ã‚µãƒ ã‚’å¾—ã‚‹ã«ã¯ã€é–¢æ•° `cbgetcrc' を用ã„る。

unsigned int cbgetcrc(const char *ptr, int size);
`ptr' ã¯é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`size' ã¯ãã®é ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã‹ã€è² æ•°ãªã‚‰ `strlen(ptr)' ã®å€¤ã¨ãªã‚‹ã€‚戻り値ã¯ã‚ªãƒ–ジェクトã®CRC32ãƒã‚§ãƒƒã‚¯ã‚µãƒ ã§ã‚る。ã“ã®é–¢æ•°ã¯QDBMãŒZLIBを有効ã«ã—ã¦ãƒ“ルドã•れãŸå ´åˆã®ã¿åˆ©ç”¨ã§ãる。

LZOを用ã„ã¦ä¸€é€£ã®ã‚ªãƒ–ジェクトを圧縮ã™ã‚‹ã«ã¯ã€é–¢æ•° `cblzoencode' を用ã„る。

char *cblzoencode(const char *ptr, int size, int *sp);
`ptr' ã¯é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`size' ã¯ãã®é ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã‹ã€è² æ•°ãªã‚‰ `strlen(ptr)' ã®å€¤ã¨ãªã‚‹ã€‚`sp' ã®å‚ç…§å…ˆã«ã¯æŠ½å‡ºã—ãŸé ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’æ ¼ç´ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰çµæžœã®é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰ `NULL' ã§ã‚る。戻り値ã®é ˜åŸŸã¯ `malloc' ã§ç¢ºä¿ã•れるã®ã§ã€ä¸è¦ã«ãªã£ãŸã‚‰ `free' ã§è§£æ”¾ã™ã‚‹ã¹ãã§ã‚る。ã“ã®é–¢æ•°ã¯QDBMãŒLZOを有効ã«ã—ã¦ãƒ“ルドã•れãŸå ´åˆã®ã¿åˆ©ç”¨ã§ãる。

LZOを用ã„ã¦åœ§ç¸®ã•れãŸã‚ªãƒ–ジェクトを伸長ã™ã‚‹ã«ã¯ã€é–¢æ•° `cblzodecode' を用ã„る。

char *cblzodecode(const char *ptr, int size, int *sp);
`ptr' ã¯é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`sp' ㌠`NULL' ã§ãªã‘れã°ã€ãã®å‚ç…§å…ˆã«æŠ½å‡ºã—ãŸé ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’æ ¼ç´ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰çµæžœã®é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰ `NULL' ã§ã‚る。戻り値ã®é ˜åŸŸã¯ã€å®Ÿéš›ã«ã¯1ãƒã‚¤ãƒˆå¤šã確ä¿ã—ã¦çµ‚端文字ãŒç½®ã‹ã‚Œã‚‹ã®ã§ã€æ–‡å­—列ã¨ã—ã¦åˆ©ç”¨ã§ãる。戻り値ã®é ˜åŸŸã¯ `malloc' ã§ç¢ºä¿ã•れるã®ã§ã€ä¸è¦ã«ãªã£ãŸã‚‰ `free' ã§è§£æ”¾ã™ã‚‹ã¹ãã§ã‚る。ã“ã®é–¢æ•°ã¯QDBMãŒLZOを有効ã«ã—ã¦ãƒ“ルドã•れãŸå ´åˆã®ã¿åˆ©ç”¨ã§ãる。

BZIP2を用ã„ã¦ä¸€é€£ã®ã‚ªãƒ–ジェクトを圧縮ã™ã‚‹ã«ã¯ã€é–¢æ•° `cbbzencode' を用ã„る。

char *cbbzencode(const char *ptr, int size, int *sp);
`ptr' ã¯é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`size' ã¯ãã®é ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã‹ã€è² æ•°ãªã‚‰ `strlen(ptr)' ã®å€¤ã¨ãªã‚‹ã€‚`sp' ã®å‚ç…§å…ˆã«ã¯æŠ½å‡ºã—ãŸé ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’æ ¼ç´ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰çµæžœã®é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰ `NULL' ã§ã‚る。戻り値ã®é ˜åŸŸã¯ `malloc' ã§ç¢ºä¿ã•れるã®ã§ã€ä¸è¦ã«ãªã£ãŸã‚‰ `free' ã§è§£æ”¾ã™ã‚‹ã¹ãã§ã‚る。ã“ã®é–¢æ•°ã¯QDBMãŒBZIP2を有効ã«ã—ã¦ãƒ“ルドã•れãŸå ´åˆã®ã¿åˆ©ç”¨ã§ãる。

BZIP2を用ã„ã¦åœ§ç¸®ã•れãŸã‚ªãƒ–ジェクトを伸長ã™ã‚‹ã«ã¯ã€é–¢æ•° `cbbzdecode' を用ã„る。

char *cbbzdecode(const char *ptr, int size, int *sp);
`ptr' ã¯é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`sp' ㌠`NULL' ã§ãªã‘れã°ã€ãã®å‚ç…§å…ˆã«æŠ½å‡ºã—ãŸé ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’æ ¼ç´ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰çµæžœã®é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰ `NULL' ã§ã‚る。戻り値ã®é ˜åŸŸã¯ã€å®Ÿéš›ã«ã¯1ãƒã‚¤ãƒˆå¤šã確ä¿ã—ã¦çµ‚端文字ãŒç½®ã‹ã‚Œã‚‹ã®ã§ã€æ–‡å­—列ã¨ã—ã¦åˆ©ç”¨ã§ãる。戻り値ã®é ˜åŸŸã¯ `malloc' ã§ç¢ºä¿ã•れるã®ã§ã€ä¸è¦ã«ãªã£ãŸã‚‰ `free' ã§è§£æ”¾ã™ã‚‹ã¹ãã§ã‚る。ã“ã®é–¢æ•°ã¯QDBMãŒBZIP2を有効ã«ã—ã¦ãƒ“ルドã•れãŸå ´åˆã®ã¿åˆ©ç”¨ã§ãる。

æ–‡å­—åˆ—ã®æ–‡å­—コードを変æ›ã™ã‚‹ã«ã¯ã€é–¢æ•° `cbiconv' を用ã„る。

char *cbiconv(const char *ptr, int size, const char *icode, const char *ocode, int *sp, int *mp);
`ptr' ã¯é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`size' ã¯ãã®é ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã‹ã€è² æ•°ãªã‚‰ `strlen(ptr)' ã®å€¤ã¨ãªã‚‹ã€‚`icode' ã¯å…¥åŠ›æ–‡å­—åˆ—ã®æ–‡å­—コードã®åå‰ã‚’指定ã™ã‚‹ã€‚`outcode' ã¯å‡ºåŠ›æ–‡å­—åˆ—ã®æ–‡å­—コードã®åå‰ã‚’指定ã™ã‚‹ã€‚`sp' ㌠`NULL' ã§ãªã‘れã°ã€ãã®å‚ç…§å…ˆã«æŠ½å‡ºã—ãŸé ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’æ ¼ç´ã™ã‚‹ã€‚`mp' ㌠`NULL' ã§ãªã‘れã°ã€ãã®å‚ç…§å…ˆã«å¤‰æ›ã«å¤±æ•—ã—ãŸæ–‡å­—æ•°ã‚’æ ¼ç´ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰çµæžœã®é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰ `NULL' ã§ã‚る。戻り値ã®é ˜åŸŸã¯ `malloc' ã§ç¢ºä¿ã•れるã®ã§ã€ä¸è¦ã«ãªã£ãŸã‚‰ `free' ã§è§£æ”¾ã™ã‚‹ã¹ãã§ã‚る。ã“ã®é–¢æ•°ã¯QDBMãŒICONVを有効ã«ã—ã¦ãƒ“ルドã•れãŸå ´åˆã®ã¿åˆ©ç”¨ã§ãる。

æ–‡å­—åˆ—ã®æ–‡å­—コードを自動判定ã™ã‚‹ã«ã¯ã€é–¢æ•° `cbencname' を用ã„る。

const char *cbencname(const char *str, int size);
`ptr' ã¯é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`size' ã¯ãã®é ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã‹ã€è² æ•°ãªã‚‰ `strlen(ptr)' ã®å€¤ã¨ãªã‚‹ã€‚`icode' ã¯å…¥åŠ›æ–‡å­—åˆ—ã®æ–‡å­—コードã®åå‰ã‚’指定ã™ã‚‹ã€‚戻り値ã¯ã‚¨ãƒ³ã‚³ãƒ¼ãƒ‰ã®åå‰ã®æ–‡å­—列ã§ã‚る。ç¾çжã§ã¯ã€US-ASCIIã€ISO-2022-JPã€Shift_JISã€CP932ã€EUC-JPã€UTF-8ã€UTF-16ã€UTF-16BEãŠã‚ˆã³UTF-16LEã«å¯¾å¿œã—ã¦ã„る。ãã®ã„ãšã‚Œã§ã‚‚ãªã„å ´åˆã¯ã€ISO-8859-1ã¨åˆ¤å®šã™ã‚‹ã€‚ã“ã®é–¢æ•°ã¯QDBMãŒICONVを有効ã«ã—ã¦ãƒ“ルドã•れãŸå ´åˆã®ã¿åˆ©ç”¨ã§ãる。

ローカル時間ã®ç§’å˜ä½ã®æ™‚差を得るã«ã¯ã€é–¢æ•° `cbjetlag' を用ã„る。

int cbjetlag(void);
戻り値ã¯ãƒ­ãƒ¼ã‚«ãƒ«æ™‚é–“ã®ç§’å˜ä½ã®æ™‚å·®ã§ã‚る。

ã‚る時間ã®ã‚°ãƒ¬ã‚´ãƒªã‚ªæš¦ã‚’å¾—ã‚‹ã«ã¯ã€é–¢æ•° `cbcalendar' を用ã„る。

void cbcalendar(time_t t, int jl, int *yearp, int *monp, int *dayp, int *hourp, int *minp, int *secp);
`t' ã¯å¯¾è±¡ã®æ™‚間を指定ã™ã‚‹ãŒã€è² æ•°ãªã‚‰ç¾åœ¨æ™‚é–“ãŒä½¿ã‚れる。`jl' ã¯ã‚ã‚‹å ´æ‰€ã®æ™‚差を秒å˜ä½ã§æŒ‡å®šã™ã‚‹ã€‚`yearp' ㌠`NULL' ã§ãªã‘れã°ã€ãã®å‚ç…§å…ˆã«å¹´ã‚’æ ¼ç´ã™ã‚‹ã€‚`monp' ㌠`NULL' ã§ãªã‘れã°ã€ãã®å‚ç…§å…ˆã«æœˆã‚’æ ¼ç´ã™ã‚‹ã€‚1ã¯1月をæ„味ã—ã€12ã¯12月をæ„味ã™ã‚‹ã€‚`dayp' ㌠`NULL' ã§ãªã‘れã°ã€ãã®å‚ç…§å…ˆã«æ—¥ã‚’æ ¼ç´ã™ã‚‹ã€‚`hourp' ㌠`NULL' ã§ãªã‘れã°ã€ãã®å‚ç…§å…ˆã«æ™‚ã‚’æ ¼ç´ã™ã‚‹ã€‚`minp' ㌠`NULL' ã§ãªã‘れã°ã€ãã®å‚ç…§å…ˆã«åˆ†ã‚’æ ¼ç´ã™ã‚‹ã€‚`secp' ㌠`NULL' ã§ãªã‘れã°ã€ãã®å‚ç…§å…ˆã«ç§’ã‚’æ ¼ç´ã™ã‚‹ã€‚

ã‚ã‚‹æ—¥ä»˜ã®æ›œæ—¥ã‚’å¾—ã‚‹ã«ã¯ã€é–¢æ•° `cbdayofweek' を用ã„る。

int cbdayofweek(int year, int mon, int day);
`year' ã¯æ—¥ä»˜ã®å¹´ã‚’指定ã™ã‚‹ã€‚`mon' ã¯æ—¥ä»˜ã®æœˆã‚’指定ã™ã‚‹ã€‚`day' ã¯æ—¥ä»˜ã®æ—¥ã‚’指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ›œæ—¥ã®å€¤ã§ã‚る。0ã¯æ—¥æ›œã‚’æ„味ã—ã€6ã¯åœŸæ›œã‚’æ„味ã™ã‚‹ã€‚

ã‚る日付をW3CDTFã®æ›¸å¼ã§è¡¨ã—ãŸæ–‡å­—列を得るã«ã¯ã€é–¢æ•° `cbdatestrwww' を用ã„る。

char *cbdatestrwww(time_t t, int jl);
`t' ã¯å¯¾è±¡ã®æ™‚間を指定ã™ã‚‹ãŒã€è² æ•°ãªã‚‰ç¾åœ¨æ™‚é–“ãŒä½¿ã‚れる。`jl' ã¯ã‚ã‚‹å ´æ‰€ã®æ™‚差を秒å˜ä½ã§æŒ‡å®šã™ã‚‹ã€‚戻り値ã¯W3CDTFã®æ›¸å¼ï¼ˆYYYY-MM-DDThh:mm:ddTZDï¼‰ã®æ–‡å­—列ã§ã‚る。戻り値ã®é ˜åŸŸã¯ `malloc' ã§ç¢ºä¿ã•れるã®ã§ã€ä¸è¦ã«ãªã£ãŸã‚‰ `free' ã§è§£æ”¾ã™ã‚‹ã¹ãã§ã‚る。

ã‚る日付をRFC 1123ã®æ›¸å¼ã§è¡¨ã—ãŸæ–‡å­—列を得るã«ã¯ã€é–¢æ•° `cbdatestrhttp' を用ã„る。

char *cbdatestrhttp(time_t t, int jl);
`t' ã¯å¯¾è±¡ã®æ™‚間を指定ã™ã‚‹ãŒã€è² æ•°ãªã‚‰ç¾åœ¨æ™‚é–“ãŒä½¿ã‚れる。`jl' ã¯ã‚ã‚‹å ´æ‰€ã®æ™‚差を秒å˜ä½ã§æŒ‡å®šã™ã‚‹ã€‚戻り値ã¯RFC 1123ã®æ›¸å¼ï¼ˆWdy, DD-Mon-YYYY hh:mm:dd TZDï¼‰ã®æ–‡å­—列ã§ã‚る。戻り値ã®é ˜åŸŸã¯ `malloc' ã§ç¢ºä¿ã•れるã®ã§ã€ä¸è¦ã«ãªã£ãŸã‚‰ `free' ã§è§£æ”¾ã™ã‚‹ã¹ãã§ã‚る。

10進数ã‹16進数ã‹W3CDTFã‹RFC 822(1123ï¼‰ã®æ›¸å¼ã§è¡¨ã—ãŸæ–‡å­—列ã‹ã‚‰æ™‚é–“ã®å€¤ã‚’å¾—ã‚‹ã«ã¯ã€é–¢æ•° `cbstrmktime' を用ã„る。

time_t cbstrmktime(const char *str);
`str' ã¯10進数ã‹16進数ã‹W3CDTFã‹RFC 822(1123ï¼‰ã®æ›¸å¼ã§è¡¨ã—ãŸæ–‡å­—列を指定ã™ã‚‹ã€‚戻り値ã¯ãã®æ™‚é–“ã®å€¤ã‹ã€æ›¸å¼ãŒä¸æ­£ãªå ´åˆã¯ -1 ã§ã‚る。10進数㫠"s" を後置ã™ã‚‹ã¨ç§’å˜ä½ã‚’æ„味ã—ã€"m" を後置ã™ã‚‹ã¨åˆ†å˜ä½ã‚’æ„味ã—ã€"h" を後置ã™ã‚‹ã¨æ™‚å˜ä½ã‚’æ„味ã—ã€"d" を後置ã™ã‚‹ã¨æ—¥å˜ä½ã‚’æ„味ã™ã‚‹ã€‚

ユーザã¨ã‚·ã‚¹ãƒ†ãƒ ã®ãƒ—ロセス時間を得るã«ã¯ã€é–¢æ•° `cbproctime' を用ã„る。

void cbproctime(double *usrp, double *sysp);
`usrp' ㌠`NULL' ã§ãªã‘れã°ã€ãã®å‚ç…§å…ˆã«ãƒ¦ãƒ¼ã‚¶æ™‚é–“ã‚’æ ¼ç´ã™ã‚‹ã€‚時間ã®å˜ä½ã¯ç§’ã§ã‚る。`sysp' ㌠`NULL' ã§ãªã‘れã°ã€ãã®å‚ç…§å…ˆã«ã‚·ã‚¹ãƒ†ãƒ æ™‚é–“ã‚’æ ¼ç´ã™ã‚‹ã€‚時間ã®å˜ä½ã¯ç§’ã§ã‚る。

標準入出力ãŒãƒã‚¤ãƒŠãƒªãƒ¢ãƒ¼ãƒ‰ã§ã‚ã‚‹ã“ã¨ã‚’ä¿è¨¼ã™ã‚‹ã«ã¯ã€é–¢æ•° `cbstdiobin' を用ã„る。

void cbstdiobin(void);
ã“ã®é–¢æ•°ã¯DOSçš„ãªãƒ•ァイルシステムã®ä¸Šã®ã‚¢ãƒ—ãƒªã‚±ãƒ¼ã‚·ãƒ§ãƒ³ã§æœ‰ç”¨ã§ã‚る。

サンプルコード

以下ã®ã‚µãƒ³ãƒ—ルコードã¯å…¸åž‹çš„ãªåˆ©ç”¨ä¾‹ã§ã‚る。

#include <cabin.h>
#include <stdlib.h>
#include <stdio.h>

int main(int argc, char **argv){
  CBDATUM *datum;
  CBLIST *list;
  CBMAP *map;
  char *buf1, *buf2;
  int i;

  /* データãƒãƒ³ãƒ‰ãƒ«ã‚’é–‹ã */
  datum = cbdatumopen("123", -1);
  /* データを連çµã™ã‚‹ */
  cbdatumcat(datum, "abc", -1);
  /* データを表示ã™ã‚‹ */
  printf("%s\n", cbdatumptr(datum));
  /* データãƒãƒ³ãƒ‰ãƒ«ã‚’é–‰ã˜ã‚‹ */
  cbdatumclose(datum);

  /* リストãƒãƒ³ãƒ‰ãƒ«ã‚’é–‹ã */
  list = cblistopen();
  /* リストã«è¦ç´ ã‚’追加ã™ã‚‹ */
  cblistpush(list, "apple", -1);
  cblistpush(list, "orange", -1);
  /* å…¨ã¦ã®è¦ç´ ã‚’表示ã™ã‚‹ */
  for(i = 0; i < cblistnum(list); i++){
    printf("%s\n", cblistval(list, i, NULL));
  }
  /* リストãƒãƒ³ãƒ‰ãƒ«ã‚’é–‰ã˜ã‚‹ */
  cblistclose(list);

  /* マップãƒãƒ³ãƒ‰ãƒ«ã‚’é–‹ã */
  map = cbmapopen();
  /* マップã«ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’追加ã™ã‚‹ */
  cbmapput(map, "dog", -1, "bowwow", -1, 1);
  cbmapput(map, "cat", -1, "meow", -1, 1);
  /* 値をå–å¾—ã—ã¦è¡¨ç¤ºã™ã‚‹ */
  printf("%s\n", cbmapget(map, "dog", -1, NULL));
  printf("%s\n", cbmapget(map, "cat", -1, NULL));
  /* マップãƒãƒ³ãƒ‰ãƒ«ã‚’é–‰ã˜ã‚‹ */
  cbmapclose(map);

  /* Base64ã®ç¬¦å·åŒ–を行ㆠ*/
  buf1 = cbbaseencode("I miss you.", -1);
  printf("%s\n", buf1);
  /* Base64ã®å¾©å…ƒã‚’行ㆠ*/
  buf2 = cbbasedecode(buf1, NULL);
  printf("%s\n", buf2);
  /* リソースを解放ã™ã‚‹ */
  free(buf2);
  free(buf1);

  /* å˜ç´”ãªãƒã‚¤ãƒ³ã‚¿ã‚’グローãƒãƒ«ã‚¬ãƒ™ãƒ¼ã‚¸ã‚³ãƒ¬ã‚¯ã‚¿ã«ç™»éŒ²ã™ã‚‹ */
  buf1 = cbmemdup("Take it easy.", -1);
  cbglobalgc(buf1, free);
  /* ãƒã‚¤ãƒ³ã‚¿ã¯åˆ©ç”¨ã§ãã‚‹ãŒè§£æ”¾ã™ã‚‹å¿…è¦ã¯ãªã„ */
  printf("%s\n", buf1);

  /* リストをグローãƒãƒ«ã‚¬ãƒ™ãƒ¼ã‚¸ã‚³ãƒ¬ã‚¯ã‚¿ã«ç™»éŒ²ã™ã‚‹ */
  list = cblistopen();
  cbglobalgc(list, (void (*)(void *))cblistclose);
  /* ãƒãƒ³ãƒ‰ãƒ«ã¯åˆ©ç”¨ã§ãã‚‹ãŒé–‰ã˜ã‚‹å¿…è¦ã¯ãªã„ */
  cblistpush(list, "Don't hesitate.", -1);
  for(i = 0; i < cblistnum(list); i++){
    printf("%s\n", cblistval(list, i, NULL));
  }

  return 0;
}

注記

Cabinを利用ã—ãŸãƒ—ログラムをビルドã™ã‚‹æ–¹æ³•ã¯ã€Depotã®å ´åˆã¨å…¨ãåŒã˜ã§ã‚る。

gcc -I/usr/local/include -o sample sample.c -L/usr/local/lib -lqdbm

スレッド間ã§åŒæ™‚ã«åŒã˜ãƒãƒ³ãƒ‰ãƒ«ã«ã‚¢ã‚¯ã‚»ã‚¹ã—ãªã„é™ã‚Šã¯ã€`cbglobalgc' を除ã„ãŸCabinã®å„関数ã¯ã‚¹ãƒ¬ãƒƒãƒ‰ã‚»ãƒ¼ãƒ•ã§ã‚る。ãŸã ã—ã€`errno' ã‚„ `malloc' ç­‰ãŒã‚¹ãƒ¬ãƒƒãƒ‰ã‚»ãƒ¼ãƒ•ãªå‡¦ç†ç³»ã§ã‚ã‚‹ã“ã¨ãŒå‰æã¨ãªã‚‹ã€‚


Cabin用コマンド

Cabinã«å¯¾å¿œã™ã‚‹ã‚³ãƒžãƒ³ãƒ‰ãƒ©ã‚¤ãƒ³ã‚¤ãƒ³ã‚¿ãƒ•ェースã¯ä»¥ä¸‹ã®ã‚‚ã®ã§ã‚る。

コマンド `cbtest' ã¯Cabinã®æ©Ÿèƒ½ãƒ†ã‚¹ãƒˆã‚„性能テストã«ç”¨ã„るツールã§ã‚る。`time' コマンドã«ã‚ˆã£ã¦ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã®å®Ÿè¡Œæ™‚間を計るã¨ã‚ˆã„ã€‚ä»¥ä¸‹ã®æ›¸å¼ã§ç”¨ã„る。`rnum' ã¯ãƒ¬ã‚³ãƒ¼ãƒ‰æ•°ã‚’指定ã™ã‚‹ã€‚

cbtest sort [-d] rnum
ソートアルゴリズムã®ãƒ†ã‚¹ãƒˆã‚’行ã†ã€‚
cbtest strstr [-d] rnum
文字列探索アルゴリズムã®ãƒ†ã‚¹ãƒˆã‚’行ã†ã€‚
cbtest list [-d] rnum
ãƒªã‚¹ãƒˆã®æ›¸ãè¾¼ã¿ãƒ†ã‚¹ãƒˆã‚’行ã†ã€‚
cbtest map [-d] rnum
ãƒžãƒƒãƒ—ã®æ›¸ãè¾¼ã¿ãƒ†ã‚¹ãƒˆã‚’行ã†ã€‚
cbtest wicked rnum
リストã¨ãƒžãƒƒãƒ—ã®å„種更新æ“作を無作為ã«é¸æŠžã—ã¦å®Ÿè¡Œã™ã‚‹ã€‚
cbtest misc
雑多ãªãƒ«ãƒ¼ãƒãƒ³ã®ãƒ†ã‚¹ãƒˆã‚’実行ã™ã‚‹ã€‚

å„オプションã¯ä»¥ä¸‹ã®æ©Ÿèƒ½ã‚’æŒã¤ã€‚

  • -d : çµæžœã®ãƒ‡ãƒ¼ã‚¿ã‚’読ã¿è¾¼ã‚“ã§è¡¨ç¤ºã™ã‚‹ã€‚

ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯å‡¦ç†ãŒæ­£å¸¸ã«çµ‚了ã™ã‚Œã° 0 ã‚’è¿”ã—ã€ã‚¨ãƒ©ãƒ¼ãŒã‚れã°ãれ以外ã®å€¤ã‚’è¿”ã—ã¦çµ‚了ã™ã‚‹ã€‚

コマンド `cbcodec' ã¯CabinãŒæä¾›ã™ã‚‹ã‚¨ãƒ³ã‚³ãƒ¼ãƒ‰ãŠã‚ˆã³ãƒ‡ã‚³ãƒ¼ãƒ‰ã®æ©Ÿèƒ½ã‚’利用ã™ã‚‹ãƒ„ールã§ã‚ã‚‹ã€‚ä»¥ä¸‹ã®æ›¸å¼ã§ç”¨ã„る。`file' ã¯å…¥åŠ›ãƒ•ã‚¡ã‚¤ãƒ«ã‚’æŒ‡å®šã™ã‚‹ãŒã€çœç•¥ã•ã‚Œã‚Œã°æ¨™æº–入力を読ã¿è¾¼ã‚€ã€‚

cbcodec url [-d] [-br] [-rs base target] [-l] [-e expr] [file]
URLエンコードã¨ãã®ãƒ‡ã‚³ãƒ¼ãƒ‰ã‚’行ã†ã€‚
cbcodec base [-d] [-l] [-c num] [-e expr] [file]
Base64エンコードã¨ãã®ãƒ‡ã‚³ãƒ¼ãƒ‰ã‚’行ã†ã€‚
cbcodec quote [-d] [-l] [-c num] [-e expr] [file]
quoted-printableエンコードã¨ãã®ãƒ‡ã‚³ãƒ¼ãƒ‰ã‚’行ã†ã€‚
cbcodec mime [-d] [-hd] [-bd] [-part num] [-l] [-ec code] [-qp] [-dc] [-e expr] [file]
MIMEエンコードã¨ãã®ãƒ‡ã‚³ãƒ¼ãƒ‰ã‚’行ã†ã€‚
cbcodec csv [-d] [-t] [-l] [-e expr] [-html] [file]
CSVã®å‡¦ç†ã‚’行ã†ã€‚デフォルトã§ã¯ãƒ¡ã‚¿æ–‡å­—ã®ã‚¨ã‚¹ã‚±ãƒ¼ãƒ—を行ã†ã€‚
cbcodec xml [-d] [-p] [-l] [-e expr] [-tsv] [file]
XMLã®å‡¦ç†ã‚’行ã†ã€‚デフォルトã§ã¯ãƒ¡ã‚¿æ–‡å­—ã®ã‚¨ã‚¹ã‚±ãƒ¼ãƒ—を行ã†ã€‚
cbcodec zlib [-d] [-gz] [-crc] [file]
ZLIBã®åœ§ç¸®ã¨ãã®ä¼¸é•·ã‚’行ã†ã€‚ZLIBを有効化ã—ã¦QDBMをビルドã—ãŸå ´åˆã«ã®ã¿åˆ©ç”¨å¯èƒ½ã§ã‚る。
cbcodec lzo [-d] [file]
LZOã®åœ§ç¸®ã¨ãã®ä¼¸é•·ã‚’行ã†ã€‚LZOを有効化ã—ã¦QDBMをビルドã—ãŸå ´åˆã«ã®ã¿åˆ©ç”¨å¯èƒ½ã§ã‚る。
cbcodec bzip [-d] [file]
BZIP2ã®åœ§ç¸®ã¨ãã®ä¼¸é•·ã‚’行ã†ã€‚BZIP2を有効化ã—ã¦QDBMをビルドã—ãŸå ´åˆã«ã®ã¿åˆ©ç”¨å¯èƒ½ã§ã‚る。
cbcodec iconv [-ic code] [-oc code] [-ol ltype] [-cn] [-um] [-wc] [file]
ICONVã«ã‚ˆã‚‹æ–‡å­—コードã®å¤‰æ›ã‚’行ã†ã€‚ICONVを有効化ã—ã¦QDBMをビルドã—ãŸå ´åˆã«ã®ã¿åˆ©ç”¨å¯èƒ½ã§ã‚る。
cbcodec date [-wf] [-rf] [-utc] [str]
`str' ã§æŒ‡å®šã—ãŸæ—¥ä»˜ã®æ–‡å­—åˆ—ã®æ›¸å¼ã‚’変æ›ã™ã‚‹ã€‚デフォルトã§ã¯ã€UNIX時間を出力ã™ã‚‹ã€‚`str' ãŒçœç•¥ã•れるã¨ã€ç¾åœ¨æ—¥æ™‚を扱ã†ã€‚

å„オプションã¯ä»¥ä¸‹ã®æ©Ÿèƒ½ã‚’æŒã¤ã€‚

  • -d : エンコード(エスケープ)ã§ã¯ãªãã€ãƒ‡ã‚³ãƒ¼ãƒ‰ï¼ˆã‚¢ãƒ³ã‚¨ã‚¹ã‚±ãƒ¼ãƒ—)を行ã†ã€‚
  • -br : URLã‚’æ§‹æˆè¦ç´ ã«åˆ†è§£ã™ã‚‹ã€‚
  • -rs : 相対URLを解決ã™ã‚‹ã€‚
  • -l : å‡ºåŠ›ã®æœ«å°¾ã«æ”¹è¡Œæ–‡å­—を加ãˆã‚‹ã€‚
  • -e expr : 入力データを直接指定ã™ã‚‹ã€‚
  • -c num : エンコードã®éš›ã®æ¡æ•°åˆ¶é™ã‚’指定ã™ã‚‹ã€‚
  • -hd : MIMEã®æ§‹æ–‡è§£æžã‚’行ã„ã€ãƒ˜ãƒƒãƒ€ã‚’TSVå½¢å¼ã§æŠ½å‡ºã™ã‚‹ã€‚
  • -bd : MIMEã®æ§‹æ–‡è§£æžã‚’行ã„ã€ãƒœãƒ‡ã‚£ã‚’抽出ã™ã‚‹ã€‚
  • -part num : MIMEã®æ§‹æ–‡è§£æžã‚’行ã„ã€ç‰¹å®šã®ãƒ‘ートを抽出ã™ã‚‹ã€‚
  • -ec code : å…¥åŠ›ã®æ–‡å­—コードを指定ã™ã‚‹ã€‚デフォルトã¯UTF-8ã§ã‚る。
  • -qp : quoted-printableエンコードを用ã„る。デフォルトã¯Base64ã§ã‚る。
  • -dc : ãƒ‡ã‚³ãƒ¼ãƒ‰çµæžœã®æ–‡å­—列ã§ãªãã€æ–‡å­—コードåを出力ã™ã‚‹ã€‚
  • -t : CSVã®æ§‹é€ ã‚’è§£æžã™ã‚‹ã€‚TSVã«å¤‰æ›ã—ã¦è¡¨ç¤ºã™ã‚‹ã€‚セル内ã®ã‚¿ãƒ–ã¨æ”¹è¡Œã¯å‰Šé™¤ã•れる。
  • -html : CSVã®æ§‹é€ ã‚’è§£æžã™ã‚‹ã€‚HTMLã«å¤‰æ›ã—ã¦å‡ºåŠ›ã™ã‚‹ã€‚
  • -p : XMLã®æ§‹æ–‡è§£æžã‚’行ã†ã€‚ã‚¿ã‚°ã¨ãƒ†ã‚­ã‚¹ãƒˆã‚»ã‚¯ã‚·ãƒ§ãƒ³ã‚’ヘッダã§åˆ†ã‘ã¦è¡¨ç¤ºã™ã‚‹ã€‚
  • -tsv : XMLã®æ§‹æ–‡è§£æžã‚’行ã†ã€‚çµæžœã‚’TSVå½¢å¼ã§å‡ºåŠ›ã™ã‚‹ã€‚テキストセクションã®ã‚¿ãƒ–ã¨æ”¹è¡Œã¯URLエンコードã•れる。
  • -gz : GZIPå½¢å¼ã‚’用ã„る。
  • -crc : CRC32ã®ãƒã‚§ãƒƒã‚¯ã‚µãƒ ã‚’ビッグエンディアンã®16進数ã§å‡ºåŠ›ã™ã‚‹ã€‚
  • -ic code : å…¥åŠ›ã®æ–‡å­—コードを指定ã™ã‚‹ã€‚デフォルトã ã¨è‡ªå‹•判定ã™ã‚‹ã€‚
  • -oc code : å‡ºåŠ›ã®æ–‡å­—コードを指定ã™ã‚‹ã€‚デフォルトã ã¨UTF-8ã«ãªã‚‹ã€‚
  • -ol ltype : 改行文字を変æ›ã™ã‚‹ã€‚`unix'(LF)ã€`dos'(CRLF)ã€`mac'(CR) ã®ã©ã‚Œã‹ã‚’指定ã™ã‚‹ã€‚
  • -cn : å…¥åŠ›ã®æ–‡å­—コードを自動判定ã—ã€ãã®åå‰ã‚’表示ã™ã‚‹ã€‚
  • -wc : å…¥åŠ›ã®æ–‡å­—コードをUTF-8ã¨ä»®å®šã—ã€ãã®æ–‡å­—数を表示ã™ã‚‹ã€‚
  • -um : UCS-2ã®æ–‡å­—ã¨ã€Cè¨€èªžã®æ–‡å­—列表ç¾ã§ã®UTF-16BEã¨UTF-8ã®å¯¾å¿œè¡¨ã‚’出力ã™ã‚‹ã€‚
  • -wf : W3CDTFã®æ›¸å¼ã§å‡ºåŠ›ã™ã‚‹ã€‚
  • -rf : RFC 1123ã®æ›¸å¼ã§å‡ºåŠ›ã™ã‚‹ã€‚
  • -utc : å”定世界時を出力ã™ã‚‹ã€‚

ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯å‡¦ç†ãŒæ­£å¸¸ã«çµ‚了ã™ã‚Œã° 0 ã‚’è¿”ã—ã€ã‚¨ãƒ©ãƒ¼ãŒã‚れã°ãれ以外ã®å€¤ã‚’è¿”ã—ã¦çµ‚了ã™ã‚‹ã€‚


Villa: 上級API

概è¦

Villaã¯QDBMã®ä¸Šç´šAPIã§ã‚りã€B+木ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’管ç†ã™ã‚‹ãƒ«ãƒ¼ãƒãƒ³ã‚’æä¾›ã™ã‚‹ã€‚å„レコードã¯ãƒ¦ãƒ¼ã‚¶ãŒæŒ‡å®šã—ãŸé †åºã§æ•´åˆ—ã•ã‚Œã¦æ ¼ç´ã•れる。ãƒãƒƒã‚·ãƒ¥ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã§ã¯ãƒ¬ã‚³ãƒ¼ãƒ‰ã®æ¤œç´¢ã¯ã‚­ãƒ¼ã®å®Œå…¨ä¸€è‡´ã«ã‚ˆã‚‹ã—ã‹ãªã‹ã£ãŸã€‚ã—ã‹ã—ã€Villaを用ã„ã‚‹ã¨ç¯„囲を指定ã—ã¦ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’検索ã™ã‚‹ã“ã¨ãŒã§ãる。å„レコードを順番ã«å‚ç…§ã™ã‚‹ã«ã¯ã‚«ãƒ¼ã‚½ãƒ«ã‚’用ã„る。データベースã«ã¯ã‚­ãƒ¼ãŒé‡è¤‡ã™ã‚‹è¤‡æ•°ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’æ ¼ç´ã™ã‚‹ã“ã¨ãŒã§ãる。ã¾ãŸã€ãƒˆãƒ©ãƒ³ã‚¶ã‚¯ã‚·ãƒ§ãƒ³æ©Ÿæ§‹ã«ã‚ˆã£ã¦ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®æ“作を一括ã—ã¦å映ã•ã›ãŸã‚Šç ´æ£„ã—ãŸã‚Šã™ã‚‹ã“ã¨ãŒã§ãる。

Villaã¯DepotãŠã‚ˆã³Cabinを基盤ã¨ã—ã¦å®Ÿè£…ã•れる。Villaã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルã¯Depotã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルãã®ã‚‚ã®ã§ã‚ã‚‹ã€‚ãƒ¬ã‚³ãƒ¼ãƒ‰ã®æ¤œç´¢ã‚„æ ¼ç´ã®å‡¦ç†é€Ÿåº¦ã¯Depotよりé…ã„ãŒã€ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルã®ã‚µã‚¤ã‚ºã¯ã‚ˆã‚Šå°ã•ã„。

Villaを使ã†ãŸã‚ã«ã¯ã€`depot.h' 㨠`cabin.h' 㨠`villa.h' 㨠`stdlib.h' をインクルードã™ã¹ãã§ã‚る。通常ã€ã‚½ãƒ¼ã‚¹ãƒ•ァイルã®å†’頭付近ã§ä»¥ä¸‹ã®è¨˜è¿°ã‚’行ã†ã€‚

#include <depot.h>
#include <cabin.h>
#include <villa.h>
#include <stdlib.h>

Villaã§ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’扱ã†éš›ã«ã¯ã€`VILLA' åž‹ã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’ãƒãƒ³ãƒ‰ãƒ«ã¨ã—ã¦ç”¨ã„る。ã“れã¯ã€`stdio.h' ã®å„種ルーãƒãƒ³ãŒãƒ•ァイル入出力㫠`FILE' åž‹ã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’用ã„ã‚‹ã®ã«ä¼¼ã¦ã„る。ãƒãƒ³ãƒ‰ãƒ«ã¯ã€é–¢æ•° `vlopen' ã§é–‹ãã€é–¢æ•° `vlclose' ã§é–‰ã˜ã‚‹ã€‚ãƒãƒ³ãƒ‰ãƒ«ã®ãƒ¡ãƒ³ãƒã‚’直接å‚ç…§ã™ã‚‹ã“ã¨ã¯æŽ¨å¥¨ã•れãªã„。データベースã«è‡´å‘½çš„ãªã‚¨ãƒ©ãƒ¼ãŒèµ·ããŸå ´åˆã¯ã€ä»¥å¾Œãã®ãƒãƒ³ãƒ‰ãƒ«ã«å¯¾ã™ã‚‹ `vlclose' を除ãå…¨ã¦ã®æ“作ã¯ä½•ã‚‚ã›ãšã«ã‚¨ãƒ©ãƒ¼ã‚’è¿”ã™ã€‚ã²ã¨ã¤ã®ãƒ—ロセスã§è¤‡æ•°ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ã‚¡ã‚¤ãƒ«ã‚’åŒæ™‚ã«åˆ©ç”¨ã™ã‚‹ã“ã¨ã¯å¯èƒ½ã§ã‚ã‚‹ãŒã€åŒã˜ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルã®è¤‡æ•°ã®ãƒãƒ³ãƒ‰ãƒ«ã‚’利用ã—ã¦ã¯ãªã‚‰ãªã„。カーソルを使ã†å‰ã«ã¯ `vlcurfirst' ã‹ `vlcurlast' ã‹ `vlcurjump' ã®ã©ã‚Œã‹ã§åˆæœŸåŒ–ã™ã‚‹å¿…è¦ãŒã‚る。`vlcurput' 㨠`vlcurout' 以外ã®é–¢æ•°ã§ãƒ¬ã‚³ãƒ¼ãƒ‰ã®æ›´æ–°ã‚„削除をã—ãŸå¾Œã«ã‚‚ã‚«ãƒ¼ã‚½ãƒ«ã‚’åˆæœŸåŒ–ã™ã‚‹å¿…è¦ãŒã‚る。

Villaã§ã‚‚Depotã¨åŒã˜ã外部変数 `dpecode' ã«ç›´å‰ã®ã‚¨ãƒ©ãƒ¼ã‚³ãƒ¼ãƒ‰ãŒè¨˜éŒ²ã•れる。エラーコードã«å¯¾å¿œã™ã‚‹ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸æ–‡å­—列を得るã«ã¯ã€é–¢æ•° `dperrmsg' を用ã„る。

API

レコードã®é †ç•ªã‚’指定ã™ã‚‹ãŸã‚ã«ã¯ã€æ¯”較関数を定義ã™ã‚‹ã€‚比較関数ã«ã¯ä»¥ä¸‹ã®åž‹ã‚’用ã„る。

typedef int(*VLCFUNC)(const char *aptr, int asiz, const char *bptr, int bsiz);
`aptr' ã¯ä¸€æ–¹ã®ã‚­ãƒ¼ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`asiz' ã¯ãã®ã‚­ãƒ¼ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã€‚`bptr' ã¯ä»–æ–¹ã®ã‚­ãƒ¼ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`bsiz' ã¯ãã®ã‚­ãƒ¼ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã€‚戻り値ã¯å‰è€…ãŒå¤§ãã‘ã‚Œã°æ­£ã€å¾Œè€…ãŒå¤§ãã‘れã°è² ã€ä¸¡è€…ãŒç­‰ä¾¡ãªã‚‰ 0 ã§ã‚る。

データベースã®ãƒãƒ³ãƒ‰ãƒ«ã‚’作æˆã™ã‚‹ã«ã¯ã€é–¢æ•° `vlopen' を用ã„る。

VILLA *vlopen(const char *name, int omode, VLCFUNC cmp);
`name' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルã®åå‰ã‚’指定ã™ã‚‹ã€‚`omode' ã¯æŽ¥ç¶šãƒ¢ãƒ¼ãƒ‰ã‚’æŒ‡å®šã—ã€`VL_OREADER' ãªã‚‰ãƒªãƒ¼ãƒ€ã€`VL_OWRITER' ãªã‚‰ãƒ©ã‚¤ã‚¿ã¨ãªã‚‹ã€‚`VL_OWRITER' ã®å ´åˆã€`VL_OCREAT' ã¾ãŸã¯ `VL_OTRUNC' ã¨ã®ãƒ“ット論ç†å’Œã«ã™ã‚‹ã“ã¨ãŒã§ãる。`VL_OCREAT' ã¯ãƒ•ァイルãŒç„¡ã„å ´åˆã«æ–°è¦ä½œæˆã™ã‚‹ã“ã¨ã‚’指示ã—ã€`VL_OTRUNC' ã¯ãƒ•ァイルãŒå­˜åœ¨ã—ã¦ã‚‚作り直ã™ã“ã¨ã‚’指示ã—ã€`VL_OZCOMP' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹å†…ã®ãƒªãƒ¼ãƒ•ã‚’ZLIBã§åœ§ç¸®ã™ã‚‹ã“ã¨ã‚’指示ã—ã€`VL_OYCOMP' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹å†…ã®ãƒªãƒ¼ãƒ•ã‚’LZOã§åœ§ç¸®ã™ã‚‹ã“ã¨ã‚’指示ã—ã€`VL_OXCOMP' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹å†…ã®ãƒªãƒ¼ãƒ•ã‚’BZIP2ã§åœ§ç¸®ã™ã‚‹ã“ã¨ã‚’指示ã™ã‚‹ã€‚`VL_OREADER' 㨠`VL_OWRITER' ã®ä¸¡æ–¹ã§ `VL_ONOLCK' ã¾ãŸã¯ `VL_OLCKNB' ã¨ã®ãƒ“ット論ç†å’Œã«ã™ã‚‹ã“ã¨ãŒã§ãã‚‹ãŒã€å‰è€…ã¯ãƒ•ァイルロックをã‹ã‘ãšã«ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’é–‹ãã“ã¨ã‚’指示ã—ã€å¾Œè€…ã¯ãƒ–ロックã›ãšã«ãƒ­ãƒƒã‚¯ã‚’ã‹ã‘ã‚‹ã“ã¨ã‚’指示ã™ã‚‹ã€‚`cmp' ã¯æ¯”較関数を指定ã™ã‚‹ã€‚`VL_CMPLEX' ã¯ã‚­ãƒ¼ã‚’è¾žæ›¸é †ã§æ¯”較ã™ã‚‹ã€‚`VL_CMPINT' ã¯ã‚­ãƒ¼ã‚’ `int' åž‹ã®ã‚ªãƒ–ジェクトã¨ã¿ãªã—ã¦æ¯”較ã™ã‚‹ã€‚`VL_CMPNUM' ã¯ã‚­ãƒ¼ã‚’ãƒ“ãƒƒã‚°ã‚¨ãƒ³ãƒ‡ã‚£ã‚¢ãƒ³ã®æ•°å€¤ã¨ã¿ãªã—ã¦æ¯”較ã™ã‚‹ã€‚`VL_CMPDEC' ã¯ã‚­ãƒ¼ã‚’10é€²æ•°ã®æ•°å€¤ã‚’è¡¨ã™æ–‡å­—列ã¨ã¿ãªã—ã¦æ¯”較ã™ã‚‹ã€‚`VLCFUNC' åž‹ã®å®£è¨€ã«åŸºã¥ã関数ã§ã‚ã‚Œã°æ¯”較関数ã¨ã—ã¦ç”¨ã„ã‚‹ã“ã¨ãŒã§ãる。åŒã˜ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«ã¯å¸¸ã«åŒã˜æ¯”較関数を用ã„ã‚‹å¿…è¦ãŒã‚る。戻り値ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã§ã‚ã‚‹ã‹ã€ã‚¨ãƒ©ãƒ¼ãªã‚‰ `NULL' ã§ã‚ã‚‹ã€‚ãƒ©ã‚¤ã‚¿ï¼ˆèª­ã¿æ›¸ã両用モード)ã§ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルを開ãéš›ã«ã¯ãã®ãƒ•ァイルã«å¯¾ã—ã¦æŽ’ä»–ãƒ­ãƒƒã‚¯ãŒã‹ã‘られã€ãƒªãƒ¼ãƒ€ï¼ˆèª­ã¿è¾¼ã¿å°‚用モード)ã§é–‹ãéš›ã«ã¯å…±æœ‰ãƒ­ãƒƒã‚¯ãŒã‹ã‘られる。ãã®éš›ã«ã¯è©²å½“ã®ãƒ­ãƒƒã‚¯ãŒã‹ã‘られるã¾ã§åˆ¶å¾¡ãŒãƒ–ロックã™ã‚‹ã€‚`VL_OZCOMP' 㨠`VL_OYCOMP' 㨠`VL_OXCOMP' ã¯QDBMãŒãれãžã‚ŒZLIBã¨LZOã¨BZIP2を有効ã«ã—ã¦ãƒ“ルドã•れãŸå ´åˆã«ã®ã¿åˆ©ç”¨ã§ãる。`VL_ONOLCK' を使ã†å ´åˆã€ã‚¢ãƒ—ãƒªã‚±ãƒ¼ã‚·ãƒ§ãƒ³ãŒæŽ’ä»–åˆ¶å¾¡ã®è²¬ä»»ã‚’è² ã†ã€‚

データベースã¨ã®æŽ¥ç¶šã‚’é–‰ã˜ã¦ãƒãƒ³ãƒ‰ãƒ«ã‚’破棄ã™ã‚‹ã«ã¯ã€é–¢æ•° `vlclose' を用ã„る。

int vlclose(VILLA *villa);
`villa' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰çœŸã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰å½ã§ã‚ã‚‹ã€‚ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®æ›´æ–°å†…容ã¯ã€æŽ¥ç¶šã‚’é–‰ã˜ãŸæ™‚点ã§åˆã‚ã¦ãƒ•ァイルã¨åŒæœŸã•れる。ライタã§ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’é–‹ã„ãŸå ´åˆã€é©åˆ‡ã«æŽ¥ç¶šã‚’é–‰ã˜ãªã„ã¨ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãŒç ´å£Šã•れる。閉ã˜ãŸãƒãƒ³ãƒ‰ãƒ«ã®é ˜åŸŸã¯è§£æ”¾ã•れるã®ã§ã€ä»¥å¾Œã¯åˆ©ç”¨ã§ããªããªã‚‹ã€‚ãƒˆãƒ©ãƒ³ã‚¶ã‚¯ã‚·ãƒ§ãƒ³ãŒæœ‰åйã§ã‚³ãƒŸãƒƒãƒˆã•れã¦ã„ãªã„å ´åˆã€ãれã¯ç ´æ£„ã•れる。

レコードを追加ã™ã‚‹ã«ã¯ã€é–¢æ•° `vlput' を用ã„る。

int vlput(VILLA *villa, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int dmode);
`villa' ã¯ãƒ©ã‚¤ã‚¿ã§æŽ¥ç¶šã—ãŸãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`kbuf' ã¯ã‚­ãƒ¼ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`ksiz' ã¯ã‚­ãƒ¼ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã‹ã€è² æ•°ãªã‚‰ `strlen(kbuf)' ã®å€¤ã¨ãªã‚‹ã€‚`vbuf' ã¯å€¤ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`vsiz' ã¯å€¤ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã‹ã€è² æ•°ãªã‚‰ `strlen(vbuf)' ã®å€¤ã¨ãªã‚‹ã€‚`dmode' ã¯ã‚­ãƒ¼ãŒæ—¢å­˜ãƒ¬ã‚³ãƒ¼ãƒ‰ã¨é‡è¤‡ã—ãŸéš›ã®åˆ¶å¾¡ã‚’指定ã™ã‚‹ã€‚`VL_DOVER' ã¯æ—¢å­˜ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã®å€¤ã‚’上書ãã—ã€`VL_DKEEP' ã¯æ—¢å­˜ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’残ã—ã¦ã‚¨ãƒ©ãƒ¼ã‚’è¿”ã—ã€`VL_DCAT' ã¯æŒ‡å®šã•れãŸå€¤ã‚’既存ã®å€¤ã®æœ«å°¾ã«åŠ ãˆã€`VL_DDUP' ã¯ã‚­ãƒ¼ã®é‡è¤‡ã‚’許ã—ã¦æŒ‡å®šã•れãŸå€¤ã‚’最後ã®å€¤ã¨ã—ã¦åŠ ãˆã€`VL_DDUPR' ã¯ã‚­ãƒ¼ã®é‡è¤‡ã‚’許ã—ã¦æŒ‡å®šã•れãŸå€¤ã‚’最åˆã®å€¤ã¨ã—ã¦åŠ ãˆã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰çœŸã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰å½ã§ã‚ã‚‹ã€‚ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®æ›´æ–°ã«ã‚ˆã£ã¦ã‚«ãƒ¼ã‚½ãƒ«ã¯ä½¿ç”¨ä¸èƒ½ã«ãªã‚‹ã€‚

レコードを削除ã™ã‚‹ã«ã¯ã€é–¢æ•° `vlout' を用ã„る。

int vlout(VILLA *villa, const char *kbuf, int ksiz);
`villa' ã¯ãƒ©ã‚¤ã‚¿ã§æŽ¥ç¶šã—ãŸãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`kbuf' ã¯ã‚­ãƒ¼ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`ksiz' ã¯ã‚­ãƒ¼ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã‹ã€è² æ•°ãªã‚‰ `strlen(kbuf)' ã®å€¤ã¨ãªã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰çœŸã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰å½ã§ã‚る。該当ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ãŒãªã„å ´åˆã‚‚å½ã‚’è¿”ã™ã€‚é‡è¤‡ã™ã‚‹ãƒ¬ã‚³ãƒ¼ãƒ‰ç¾¤ã®ã‚­ãƒ¼ãŒæŒ‡å®šã•れãŸå ´åˆã€ãã®æœ€åˆã®ã‚‚ã®ãŒå‰Šé™¤ã•ã‚Œã‚‹ã€‚ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®æ›´æ–°ã«ã‚ˆã£ã¦ã‚«ãƒ¼ã‚½ãƒ«ã¯ä½¿ç”¨ä¸èƒ½ã«ãªã‚‹ã€‚

レコードをå–å¾—ã™ã‚‹ã«ã¯ã€é–¢æ•° `vlget' を用ã„る。

char *vlget(VILLA *villa, const char *kbuf, int ksiz, int *sp);
`villa' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`kbuf' ã¯ã‚­ãƒ¼ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`ksiz' ã¯ã‚­ãƒ¼ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã‹ã€è² æ•°ãªã‚‰ `strlen(kbuf)' ã®å€¤ã¨ãªã‚‹ã€‚`sp' ㌠`NULL' ã§ãªã‘れã°ã€ãã®å‚ç…§å…ˆã«æŠ½å‡ºã—ãŸé ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’æ ¼ç´ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰å€¤ã‚’æ ¼ç´ã—ãŸé ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰ `NULL' ã§ã‚る。該当ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ãŒãªã„å ´åˆã‚‚ `NULL' ã‚’è¿”ã™ã€‚é‡è¤‡ã™ã‚‹ãƒ¬ã‚³ãƒ¼ãƒ‰ç¾¤ã®ã‚­ãƒ¼ãŒæŒ‡å®šã•れãŸå ´åˆã€ãã®æœ€åˆã®ã‚‚ã®ãŒé¸æŠžã•れる。戻り値ã®é ˜åŸŸã¯ã€å®Ÿéš›ã«ã¯1ãƒã‚¤ãƒˆå¤šã確ä¿ã—ã¦çµ‚端文字ãŒç½®ã‹ã‚Œã‚‹ã®ã§ã€æ–‡å­—列ã¨ã—ã¦åˆ©ç”¨ã§ãる。戻り値ã®é ˜åŸŸã¯ `malloc' ã§ç¢ºä¿ã•れるã®ã§ã€ä¸è¦ã«ãªã£ãŸã‚‰ `free' ã§è§£æ”¾ã™ã‚‹ã¹ãã§ã‚る。

レコードã®å€¤ã®ã‚µã‚¤ã‚ºã‚’å–å¾—ã™ã‚‹ã«ã¯ã€é–¢æ•° `vlvsiz' を用ã„る。

int vlvsiz(VILLA *villa, const char *kbuf, int ksiz);
`villa' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`kbuf' ã¯ã‚­ãƒ¼ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`ksiz' ã¯ã‚­ãƒ¼ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã‹ã€è² æ•°ãªã‚‰ `strlen(kbuf)' ã®å€¤ã¨ãªã‚‹ã€‚戻り値ã¯è©²å½“レコードã®å€¤ã®ã‚µã‚¤ã‚ºã§ã‚ã‚‹ãŒã€è©²å½“ãŒãªã„å ´åˆã‚„エラーã®å ´åˆã¯ -1 ã§ã‚る。複数ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ãŒè©²å½“ã™ã‚‹å ´åˆã¯ã€æœ€åˆã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã®å€¤ã®ã‚µã‚¤ã‚ºã‚’è¿”ã™ã€‚

キーã«ä¸€è‡´ã™ã‚‹ãƒ¬ã‚³ãƒ¼ãƒ‰ã®æ•°ã‚’å–å¾—ã™ã‚‹ã«ã¯ã€é–¢æ•° `vlvnum' を用ã„る。

int vlvnum(VILLA *villa, const char *kbuf, int ksiz);
`villa' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`kbuf' ã¯ã‚­ãƒ¼ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`ksiz' ã¯ã‚­ãƒ¼ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã‹ã€è² æ•°ãªã‚‰ `strlen(kbuf)' ã®å€¤ã¨ãªã‚‹ã€‚戻り値ã¯è©²å½“レコードã®å€¤ã®æ•°ã§ã‚りã€è©²å½“ãŒãªã„å ´åˆã‚„エラーã®å ´åˆã¯ 0 ã§ã‚る。

キーã«ä¸€è‡´ã™ã‚‹è¤‡æ•°ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’追加ã™ã‚‹ã«ã¯ã€é–¢æ•° `vlputlist' を用ã„る。

int vlputlist(VILLA *villa, const char *kbuf, int ksiz, const CBLIST *vals);
`villa' ã¯ãƒ©ã‚¤ã‚¿ã§æŽ¥ç¶šã—ãŸãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`kbuf' ã¯ã‚­ãƒ¼ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`ksiz' ã¯ã‚­ãƒ¼ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã‹ã€è² æ•°ãªã‚‰ `strlen(kbuf)' ã®å€¤ã¨ãªã‚‹ã€‚`vals' ã¯å€¤ã®ãƒªã‚¹ãƒˆã®ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚リストã¯ç©ºã§ã‚ã£ã¦ã¯ãªã‚‰ãªã„ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰çœŸã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰å½ã§ã‚ã‚‹ã€‚ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®æ›´æ–°ã«ã‚ˆã£ã¦ã‚«ãƒ¼ã‚½ãƒ«ã¯ä½¿ç”¨ä¸èƒ½ã«ãªã‚‹ã€‚

キーã«ä¸€è‡´ã™ã‚‹å…¨ã¦ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’削除ã™ã‚‹ã«ã¯ã€é–¢æ•° `vloutlist' を用ã„る。

int vloutlist(VILLA *villa, const char *kbuf, int ksiz);
`villa' ã¯ãƒ©ã‚¤ã‚¿ã§æŽ¥ç¶šã—ãŸãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`kbuf' ã¯ã‚­ãƒ¼ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`ksiz' ã¯ã‚­ãƒ¼ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã‹ã€è² æ•°ãªã‚‰ `strlen(kbuf)' ã®å€¤ã¨ãªã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰çœŸã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰å½ã§ã‚る。該当ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ãŒãªã„å ´åˆã‚‚å½ã‚’è¿”ã™ã€‚ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®æ›´æ–°ã«ã‚ˆã£ã¦ã‚«ãƒ¼ã‚½ãƒ«ã¯ä½¿ç”¨ä¸èƒ½ã«ãªã‚‹ã€‚

キーã«ä¸€è‡´ã™ã‚‹å…¨ã¦ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’å–å¾—ã™ã‚‹ã«ã¯ã€é–¢æ•° `vlgetlist' を用ã„る。

CBLIST *vlgetlist(VILLA *villa, const char *kbuf, int ksiz);
`villa' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`kbuf' ã¯ã‚­ãƒ¼ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`ksiz' ã¯ã‚­ãƒ¼ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã‹ã€è² æ•°ãªã‚‰ `strlen(kbuf)' ã®å€¤ã¨ãªã‚‹ã€‚戻り値ã¯ä¸€è‡´ã™ã‚‹ãƒ¬ã‚³ãƒ¼ãƒ‰ã®å€¤ã®ãƒªã‚¹ãƒˆã®ãƒãƒ³ãƒ‰ãƒ«ã§ã‚ã‚‹ã‹ã€ã‚¨ãƒ©ãƒ¼ãªã‚‰ `NULL' ã§ã‚る。該当ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ãŒãªã„å ´åˆã‚‚ `NULL' ã‚’è¿”ã™ã€‚戻り値ã®ãƒãƒ³ãƒ‰ãƒ«ã¯é–¢æ•° `cblistopen' ã§é–‹ã‹ã‚Œã‚‹ã®ã§ã€ä¸è¦ã«ãªã£ãŸã‚‰ `cblistclose' ã§é–‰ã˜ã‚‹ã¹ãã§ã‚る。

キーã«ä¸€è‡´ã™ã‚‹å…¨ã¦ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã®é€£çµã—ãŸå€¤ã‚’å–å¾—ã™ã‚‹ã«ã¯ã€é–¢æ•° `vlgetcat' を用ã„る。

char *vlgetcat(VILLA *villa, const char *kbuf, int ksiz, int *sp);
`villa' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`kbuf' ã¯ã‚­ãƒ¼ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`ksiz' ã¯ã‚­ãƒ¼ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã‹ã€è² æ•°ãªã‚‰ `strlen(kbuf)' ã®å€¤ã¨ãªã‚‹ã€‚`sp' ㌠`NULL' ã§ãªã‘れã°ã€ãã®å‚ç…§å…ˆã«æŠ½å‡ºã—ãŸé ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’æ ¼ç´ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰é€£çµã—ãŸå€¤ã‚’æ ¼ç´ã—ãŸé ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰ `NULL' ã§ã‚る。該当ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ãŒãªã„å ´åˆã‚‚ `NULL' ã‚’è¿”ã™ã€‚戻り値ã®é ˜åŸŸã¯ã€å®Ÿéš›ã«ã¯1ãƒã‚¤ãƒˆå¤šã確ä¿ã—ã¦çµ‚端文字ãŒç½®ã‹ã‚Œã‚‹ã®ã§ã€æ–‡å­—列ã¨ã—ã¦åˆ©ç”¨ã§ãる。戻り値ã®é ˜åŸŸã¯ `malloc' ã§ç¢ºä¿ã•れるã®ã§ã€ä¸è¦ã«ãªã£ãŸã‚‰ `free' ã§è§£æ”¾ã™ã‚‹ã¹ãã§ã‚る。

カーソルを最åˆã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã«ç§»å‹•ã•ã›ã‚‹ã«ã¯ã€é–¢æ•° `vlcurfirst' を用ã„る。

int vlcurfirst(VILLA *villa);
`villa' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰çœŸã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰å½ã§ã‚る。データベースãŒç©ºã®å ´åˆã‚‚å½ã‚’è¿”ã™ã€‚

カーソルを最後ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã«ç§»å‹•ã•ã›ã‚‹ã«ã¯ã€é–¢æ•° `vlcurlast' を用ã„る。

int vlcurlast(VILLA *villa);
`villa' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰çœŸã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰å½ã§ã‚る。データベースãŒç©ºã®å ´åˆã‚‚å½ã‚’è¿”ã™ã€‚

カーソルをå‰ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã«ç§»å‹•ã•ã›ã‚‹ã«ã¯ã€é–¢æ•° `vlcurprev' を用ã„る。

int vlcurprev(VILLA *villa);
`villa' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰çœŸã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰å½ã§ã‚る。å‰ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ãŒãªã„å ´åˆã‚‚å½ã‚’è¿”ã™ã€‚

カーソルを次ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã«ç§»å‹•ã•ã›ã‚‹ã«ã¯ã€é–¢æ•° `vlcurnext' を用ã„る。

int vlcurnext(VILLA *villa);
`villa' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰çœŸã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰å½ã§ã‚る。次ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ãŒãªã„å ´åˆã‚‚å½ã‚’è¿”ã™ã€‚

カーソルを特定ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã®å‰å¾Œã«ç§»å‹•ã•ã›ã‚‹ã«ã¯ã€é–¢æ•° `vlcurjump' を用ã„る。

int vlcurjump(VILLA *villa, const char *kbuf, int ksiz, int jmode);
`villa' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`kbuf' ã¯ã‚­ãƒ¼ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`ksiz' ã¯ã‚­ãƒ¼ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã‹ã€è² æ•°ãªã‚‰ `strlen(kbuf)' ã®å€¤ã¨ãªã‚‹ã€‚`jmode' ã¯è©³ç´°ãªèª¿æ•´ã‚’指定ã™ã‚‹ã€‚`VL_JFORWARD' ã¯ã‚­ãƒ¼ãŒåŒã˜ãƒ¬ã‚³ãƒ¼ãƒ‰ç¾¤ã®æœ€åˆã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã«ã‚«ãƒ¼ã‚½ãƒ«ãŒè¨­å®šã•れã€ã¾ãŸå®Œå…¨ã«ä¸€è‡´ã™ã‚‹ãƒ¬ã‚³ãƒ¼ãƒ‰ãŒãªã„å ´åˆã¯æ¬¡ã®å€™è£œã«ã‚«ãƒ¼ã‚½ãƒ«ãŒè¨­å®šã•れるã“ã¨ã‚’æ„味ã™ã‚‹ã€‚`VL_JBACKWORD' ã¯ã‚­ãƒ¼ãŒåŒã˜ãƒ¬ã‚³ãƒ¼ãƒ‰ç¾¤ã®æœ€å¾Œã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã«ã‚«ãƒ¼ã‚½ãƒ«ãŒè¨­å®šã•れã€ã¾ãŸå®Œå…¨ã«ä¸€è‡´ã™ã‚‹ãƒ¬ã‚³ãƒ¼ãƒ‰ãŒãªã„å ´åˆã¯å‰ã®å€™è£œã«ã‚«ãƒ¼ã‚½ãƒ«ãŒè¨­å®šã•れるã“ã¨ã‚’æ„味ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰çœŸã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰å½ã§ã‚る。æ¡ä»¶ã«ä¸€è‡´ã™ã‚‹ãƒ¬ã‚³ãƒ¼ãƒ‰ãŒãªã„å ´åˆã‚‚å½ã‚’è¿”ã™ã€‚

カーソルã®ã‚るレコードã®ã‚­ãƒ¼ã‚’å–å¾—ã™ã‚‹ã«ã¯ã€é–¢æ•° `vlcurkey' を用ã„る。

char *vlcurkey(VILLA *villa, int *sp);
`villa' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`sp' ㌠`NULL' ã§ãªã‘れã°ã€ãã®å‚ç…§å…ˆã«æŠ½å‡ºã—ãŸé ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’æ ¼ç´ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰å€¤ã‚’æ ¼ç´ã—ãŸé ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰ `NULL' ã§ã‚る。該当ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ãŒãªã„å ´åˆã‚‚ `NULL' ã‚’è¿”ã™ã€‚戻り値ã®é ˜åŸŸã¯ã€å®Ÿéš›ã«ã¯1ãƒã‚¤ãƒˆå¤šã確ä¿ã—ã¦çµ‚端文字ãŒç½®ã‹ã‚Œã‚‹ã®ã§ã€æ–‡å­—列ã¨ã—ã¦åˆ©ç”¨ã§ãる。戻り値ã®é ˜åŸŸã¯ `malloc' ã§ç¢ºä¿ã•れるã®ã§ã€ä¸è¦ã«ãªã£ãŸã‚‰ `free' ã§è§£æ”¾ã™ã‚‹ã¹ãã§ã‚る。

カーソルã®ã‚るレコードã®å€¤ã‚’å–å¾—ã™ã‚‹ã«ã¯ã€é–¢æ•° `vlcurkey' を用ã„る。

char *vlcurval(VILLA *villa, int *sp);
`villa' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`sp' ㌠`NULL' ã§ãªã‘れã°ã€ãã®å‚ç…§å…ˆã«æŠ½å‡ºã—ãŸé ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’æ ¼ç´ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰å€¤ã‚’æ ¼ç´ã—ãŸé ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰ `NULL' ã§ã‚る。該当ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ãŒãªã„å ´åˆã‚‚ `NULL' ã‚’è¿”ã™ã€‚戻り値ã®é ˜åŸŸã¯ã€å®Ÿéš›ã«ã¯1ãƒã‚¤ãƒˆå¤šã確ä¿ã—ã¦çµ‚端文字ãŒç½®ã‹ã‚Œã‚‹ã®ã§ã€æ–‡å­—列ã¨ã—ã¦åˆ©ç”¨ã§ãる。戻り値ã®é ˜åŸŸã¯ `malloc' ã§ç¢ºä¿ã•れるã®ã§ã€ä¸è¦ã«ãªã£ãŸã‚‰ `free' ã§è§£æ”¾ã™ã‚‹ã¹ãã§ã‚る。

カーソルã®ã‚るレコードã®å‘¨è¾ºã«ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’挿入ã™ã‚‹ã«ã¯ã€é–¢æ•° `vlcurput' を用ã„る。

int vlcurput(VILLA *villa, const char *vbuf, int vsiz, int cpmode);
`villa' ã¯ãƒ©ã‚¤ã‚¿ã§æŽ¥ç¶šã—ãŸãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`vbuf' ã¯å€¤ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’指定ã™ã‚‹ã€‚`vsiz' ã¯å€¤ã®ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã‹ã€è² æ•°ãªã‚‰ `strlen(vbuf)' ã®å€¤ã¨ãªã‚‹ã€‚`cpmode' ã¯è©³ç´°ãªèª¿æ•´ã‚’指定ã™ã‚‹ã€‚`VL_CPCURRENT' ã¯ç¾åœ¨ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã®å€¤ã‚’上書ãã™ã‚‹ã“ã¨ã‚’指示ã—ã€`VL_CPBEFORE' ã¯ã‚«ãƒ¼ã‚½ãƒ«ã®ç›´å‰ã«ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’挿入ã™ã‚‹ã“ã¨ã‚’指示ã—ã€`VL_CPAFTER' ã¯ã‚«ãƒ¼ã‚½ãƒ«ã®ç›´å¾Œã«ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’挿入ã™ã‚‹ã“ã¨ã‚’指示ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰çœŸã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰å½ã§ã‚る。該当ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ãŒãªã„å ´åˆã‚‚å½ã‚’è¿”ã™ã€‚挿入æ“作ã®å¾Œã«ã¯ã€ã‚«ãƒ¼ã‚½ãƒ«ã¯æŒ¿å…¥ã•れãŸãƒ¬ã‚³ãƒ¼ãƒ‰ã®ä½ç½®ã«ç§»å‹•ã™ã‚‹ã€‚

カーソルã®ã‚るレコードを削除ã™ã‚‹ã«ã¯ã€é–¢æ•° `vlcurout' を用ã„る。

int vlcurout(VILLA *villa);
`villa' ã¯ãƒ©ã‚¤ã‚¿ã§æŽ¥ç¶šã—ãŸãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰çœŸã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰å½ã§ã‚る。該当ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ãŒãªã„å ´åˆã‚‚å½ã‚’è¿”ã™ã€‚削除æ“作ã®å¾Œã«ã¯ã€å¯èƒ½ã§ã‚れã°ã‚«ãƒ¼ã‚½ãƒ«ã¯æ¬¡ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã«ç§»å‹•ã™ã‚‹ã€‚

性能を調整ã™ã‚‹ãƒ‘ラメータを指定ã™ã‚‹ã«ã¯ã€é–¢æ•° `vlsettuning' を用ã„る。

void vlsettuning(VILLA *villa, int lrecmax, int nidxmax, int lcnum, int ncnum);
`villa' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`lrecmax' ã¯B+木ã®ã²ã¨ã¤ã®ãƒªãƒ¼ãƒ•ã«å…¥ã‚Œã‚‹ãƒ¬ã‚³ãƒ¼ãƒ‰ã®æœ€å¤§æ•°ã‚’指定ã™ã‚‹ãŒã€0 以下ãªã‚‰ãƒ‡ãƒ•ォルト値ãŒä½¿ã‚れる。`nidxmax' ã¯B+木ã®éžãƒªãƒ¼ãƒ•ノードã«å…¥ã‚Œã‚‹ã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹ã®æœ€å¤§æ•°ã‚’指定ã™ã‚‹ãŒã€0 以下ãªã‚‰ãƒ‡ãƒ•ォルト値ãŒä½¿ã‚れる。`lcnum' ã¯ã‚­ãƒ£ãƒƒã‚·ãƒ¥ã«å…¥ã‚Œã‚‹ãƒªãƒ¼ãƒ•ã®æœ€å¤§æ•°ã‚’指定ã™ã‚‹ãŒã€0 以下ãªã‚‰ãƒ‡ãƒ•ォルト値ãŒä½¿ã‚れる。`ncnum' ã¯ã‚­ãƒ£ãƒƒã‚·ãƒ¥ã«å…¥ã‚Œã‚‹éžãƒªãƒ¼ãƒ•ãƒŽãƒ¼ãƒ‰ã®æœ€å¤§æ•°ã‚’指定ã™ã‚‹ãŒã€0 以下ãªã‚‰ãƒ‡ãƒ•ォルト値ãŒä½¿ã‚れる。デフォルトã®è¨­å®šã¯ `vlsettuning(49, 192, 1024, 512)' ã«ç›¸å½“ã™ã‚‹ã€‚性能調整ã®ãƒ‘ラメータã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«ä¿å­˜ã•れãªã„ã®ã§ã€ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’é–‹ãåº¦ã«æŒ‡å®šã™ã‚‹å¿…è¦ãŒã‚る。

データベースã®ãƒ•リーブロックプールã®ã‚µã‚¤ã‚ºè¨­å®šã™ã‚‹ã«ã¯ã€é–¢æ•° `vlsetfbpsiz' を用ã„る。

int vlsetfbpsiz(VILLA *villa, int size);
`villa' ã¯ãƒ©ã‚¤ã‚¿ã§æŽ¥ç¶šã—ãŸãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`size' ã¯ãƒ•リーブロックプールã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰çœŸã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰å½ã§ã‚る。フリーブロックプールã®ãƒ‡ãƒ•ォルトã®ã‚µã‚¤ã‚ºã¯256ã§ã‚る。サイズをより大ããã™ã‚‹ã¨ã€ãƒ¬ã‚³ãƒ¼ãƒ‰ã®ä¸Šæ›¸ãを繰り返ã™éš›ã®ç©ºé–“効率ã¯ä¸ŠãŒã‚‹ãŒã€æ™‚間効率ãŒä¸‹ãŒã‚‹ã€‚

データベースを更新ã—ãŸå†…容をファイルã¨ãƒ‡ãƒã‚¤ã‚¹ã«åŒæœŸã•ã›ã‚‹ã«ã¯ã€é–¢æ•° `vlsync' を用ã„る。

int vlsync(VILLA *villa);
`villa' ã¯ãƒ©ã‚¤ã‚¿ã§æŽ¥ç¶šã—ãŸãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰çœŸã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰å½ã§ã‚る。ã“ã®é–¢æ•°ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’é–‰ã˜ãªã„ã†ã¡ã«åˆ¥ãƒ—ロセスã«ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルを利用ã•ã›ã‚‹å ´åˆã«å½¹ç«‹ã¤ã€‚ãƒˆãƒ©ãƒ³ã‚¶ã‚¯ã‚·ãƒ§ãƒ³ãŒæœ‰åйãªé–“ã¯ã“ã®é–¢æ•°ã‚’使用ã™ã¹ãã§ã¯ãªã„。

データベースを最é©åŒ–ã™ã‚‹ã«ã¯ã€é–¢æ•° `vloptimize' を用ã„る。

int vloptimize(VILLA *villa);
`villa' ã¯ãƒ©ã‚¤ã‚¿ã§æŽ¥ç¶šã—ãŸãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰çœŸã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰å½ã§ã‚る。レコードを削除ã—ãŸã‚Šã€ç½®æ›ãƒ¢ãƒ¼ãƒ‰ã‚„連çµãƒ¢ãƒ¼ãƒ‰ã§æ›¸ãè¾¼ã¿ã‚’繰り返ã—ãŸã‚Šã™ã‚‹å ´åˆã¯ã€ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹å†…ã«ä¸è¦ãªé ˜åŸŸãŒè“„ç©ã™ã‚‹ãŒã€ã“ã®é–¢æ•°ã¯ãれを解消ã™ã‚‹ã®ã«å½¹ç«‹ã¤ã€‚ãƒˆãƒ©ãƒ³ã‚¶ã‚¯ã‚·ãƒ§ãƒ³ãŒæœ‰åйãªé–“ã¯ã“ã®é–¢æ•°ã‚’使用ã™ã¹ãã§ã¯ãªã„。

データベースã®åå‰ã‚’å¾—ã‚‹ã«ã¯ã€é–¢æ•° `vlname' を用ã„る。

char *vlname(VILLA *villa);
`villa' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰åå‰ã‚’æ ¼ç´ã—ãŸé ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰ `NULL' ã§ã‚る。戻り値ã®é ˜åŸŸã¯ `malloc' ã§ç¢ºä¿ã•れるã®ã§ã€ä¸è¦ã«ãªã£ãŸã‚‰ `free' ã§è§£æ”¾ã™ã‚‹ã¹ãã§ã‚る。

データベースファイルã®ã‚µã‚¤ã‚ºã‚’å¾—ã‚‹ã«ã¯ã€é–¢æ•° `vlfsiz' を用ã„る。

int vlfsiz(VILLA *villa);
`villa' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルã®ã‚µã‚¤ã‚ºã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰ -1 ã§ã‚る。I/Oãƒãƒƒãƒ•ã‚¡ã«ã‚ˆã‚Šã€æˆ»ã‚Šå€¤ã¯å®Ÿéš›ã®ã‚µã‚¤ã‚ºã‚ˆã‚Šå°ã•ããªã‚‹å ´åˆãŒã‚る。

B+木ã®ãƒªãƒ¼ãƒ•ãƒŽãƒ¼ãƒ‰ã®æ•°ã‚’å¾—ã‚‹ã«ã¯ã€é–¢æ•° `vllnum' を用ã„る。

int vllnum(VILLA *villa);
`villa' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰ãƒªãƒ¼ãƒ•ãƒŽãƒ¼ãƒ‰ã®æ•°ã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰ -1 ã§ã‚る。

B+木ã®éžãƒªãƒ¼ãƒ•ãƒŽãƒ¼ãƒ‰ã®æ•°ã‚’å¾—ã‚‹ã«ã¯ã€é–¢æ•° `vlnnum' を用ã„る。

int vlnnum(VILLA *villa);
`villa' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰éžãƒªãƒ¼ãƒ•ãƒŽãƒ¼ãƒ‰ã®æ•°ã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰ -1 ã§ã‚る。

データベースã®ãƒ¬ã‚³ãƒ¼ãƒ‰æ•°ã‚’å¾—ã‚‹ã«ã¯ã€é–¢æ•° `vlrnum' を用ã„る。

int vlrnum(VILLA *villa);
`villa' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®ãƒ¬ã‚³ãƒ¼ãƒ‰æ•°ã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰ -1 ã§ã‚る。

データベースãƒãƒ³ãƒ‰ãƒ«ãŒãƒ©ã‚¤ã‚¿ã‹ã©ã†ã‹ã‚’調ã¹ã‚‹ã«ã¯ã€é–¢æ•° `vlwritable' を用ã„る。

int vlwritable(VILLA *villa);
`villa' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚戻り値ã¯ãƒ©ã‚¤ã‚¿ãªã‚‰çœŸã§ã‚りã€ãã†ã§ãªã‘れã°å½ã§ã‚る。

データベースã«è‡´å‘½çš„エラーãŒèµ·ããŸã‹ã©ã†ã‹ã‚’調ã¹ã‚‹ã«ã¯ã€é–¢æ•° `vlfatalerror' を用ã„る。

int vlfatalerror(VILLA *villa);
`villa' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚戻り値ã¯è‡´å‘½çš„エラーãŒã‚れã°çœŸã§ã‚りã€ãã†ã§ãªã‘れã°å½ã§ã‚る。

データベースファイルã®inode番å·ã‚’å¾—ã‚‹ã«ã¯ã€é–¢æ•° `vlinode' を用ã„る。

int vlinode(VILLA *villa);
`villa' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚戻り値ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルã®inode番å·ã§ã‚る。

ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®æœ€çµ‚更新時刻を得るã«ã¯ã€é–¢æ•° `vlmtime' を用ã„る。

time_t vlmtime(VILLA *villa);
`villa' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚戻り値ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®æœ€çµ‚更新時刻ã§ã‚る。

トランザクションを開始ã™ã‚‹ã«ã¯ã€é–¢æ•° `vltranbegin' を用ã„る。

int vltranbegin(VILLA *villa);
`villa' ã¯ãƒ©ã‚¤ã‚¿ã§æŽ¥ç¶šã—ãŸãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰çœŸã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰å½ã§ã‚る。ã“ã®é–¢æ•°ã¯ãƒžãƒ«ãƒã‚¹ãƒ¬ãƒƒãƒ‰ã§ã®ç›¸äº’排他制御を行ã‚ãªã„ã®ã§ã€ã‚¢ãƒ—リケーションãŒãã®è²¬ä»»ã‚’è² ã†ã€‚一ã¤ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã§åŒæ™‚ã«æœ‰åйã«ã§ãるトランザクションã¯ä¸€ã¤ã ã‘ã§ã‚る。

トランザクションをコミットã™ã‚‹ã«ã¯ã€é–¢æ•° `vltrancommit' を用ã„る。

int vltrancommit(VILLA *villa);
`villa' ã¯ãƒ©ã‚¤ã‚¿ã§æŽ¥ç¶šã—ãŸãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰çœŸã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰å½ã§ã‚る。トランザクションã®ä¸­ã§ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®æ›´æ–°ã¯ã‚³ãƒŸãƒƒãƒˆãŒæˆåŠŸã—ãŸæ™‚ã«ç¢ºå®šã™ã‚‹ã€‚

トランザクションを破棄ã™ã‚‹ã«ã¯ã€é–¢æ•° `vltranabort' を用ã„る。

int vltranabort(VILLA *villa);
`villa' ã¯ãƒ©ã‚¤ã‚¿ã§æŽ¥ç¶šã—ãŸãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰çœŸã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰å½ã§ã‚る。トランザクションã®ä¸­ã§ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®æ›´æ–°ã¯ã‚¢ãƒœãƒ¼ãƒˆã—ãŸæ™‚ã«ã¯ç ´æ£„ã•れる。データベースã®çŠ¶æ…‹ã¯ãƒˆãƒ©ãƒ³ã‚¶ã‚¯ã‚·ãƒ§ãƒ³ã®å‰ã®çŠ¶æ…‹ã«ãƒ­ãƒ¼ãƒ«ãƒãƒƒã‚¯ã•れる。

データベースファイルを削除ã™ã‚‹ã«ã¯ã€é–¢æ•° `vlremove' を用ã„る。

int vlremove(const char *name);
`name' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルã®åå‰ã‚’指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰çœŸã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰å½ã§ã‚る。

壊れãŸãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルを修復ã™ã‚‹ã«ã¯ã€é–¢æ•° `vlrepair' を用ã„る。

int vlrepair(const char *name, VLCFUNC cmp);
`name' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルã®åå‰ã‚’指定ã™ã‚‹ã€‚`cmp' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ã‚¡ã‚¤ãƒ«ã®æ¯”較関数を指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰çœŸã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰å½ã§ã‚る。修復ã•れãŸãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®å…¨ãƒ¬ã‚³ãƒ¼ãƒ‰ãŒå…ƒæ¥ã‚‚ã—ãã¯æœŸå¾…ã•ã‚Œã‚‹çŠ¶æ…‹ã«æˆ»ã‚‹ä¿è¨¼ã¯ãªã„。

å…¨ã¦ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’エンディアンéžä¾å­˜ã®ãƒ‡ãƒ¼ã‚¿ã¨ã—ã¦ãƒ€ãƒ³ãƒ—ã™ã‚‹ã«ã¯ã€é–¢æ•° `vlexportdb' を用ã„る。

int vlexportdb(VILLA *villa, const char *name);
`villa' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`name' ã¯å‡ºåŠ›ãƒ•ã‚¡ã‚¤ãƒ«ã®åå‰ã‚’指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰çœŸã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰å½ã§ã‚る。

エンディアンéžä¾å­˜ãƒ‡ãƒ¼ã‚¿ã‹ã‚‰å…¨ã¦ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’ロードã™ã‚‹ã«ã¯ã€é–¢æ•° `vlimportdb' を用ã„る。

int vlimportdb(VILLA *villa, const char *name);
`villa' ã¯ãƒ©ã‚¤ã‚¿ã§æŽ¥ç¶šã—ãŸãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚データベースã¯ç©ºã§ãªã‘れã°ãªã‚‰ãªã„。`name' ã¯å…¥åŠ›ãƒ•ã‚¡ã‚¤ãƒ«ã®åå‰ã‚’指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰çœŸã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰å½ã§ã‚る。

サンプルコード

åå‰ã¨å¯¾å¿œã•ã›ã¦é›»è©±ç•ªå·ã‚’æ ¼ç´ã—ã€ãれを検索ã™ã‚‹ã‚¢ãƒ—リケーションã®ã‚µãƒ³ãƒ—ルコードを以下ã«ç¤ºã™ã€‚

#include <depot.h>
#include <cabin.h>
#include <villa.h>
#include <stdlib.h>
#include <stdio.h>

#define NAME     "mikio"
#define NUMBER   "000-1234-5678"
#define DBNAME   "book"

int main(int argc, char **argv){
  VILLA *villa;
  char *val;

  /* データベースを開ã */
  if(!(villa = vlopen(DBNAME, VL_OWRITER | VL_OCREAT, VL_CMPLEX))){
    fprintf(stderr, "vlopen: %s\n", dperrmsg(dpecode));
    return 1;
  }

  /* レコードを格ç´ã™ã‚‹ */
  if(!vlput(villa, NAME, -1, NUMBER, -1, VL_DOVER)){
    fprintf(stderr, "vlput: %s\n", dperrmsg(dpecode));
  }

  /* レコードをå–å¾—ã™ã‚‹ */
  if(!(val = vlget(villa, NAME, -1, NULL))){
    fprintf(stderr, "vlget: %s\n", dperrmsg(dpecode));
  } else {
    printf("Name: %s\n", NAME);
    printf("Number: %s\n", val);
    free(val);
  }

  /* データベースを閉ã˜ã‚‹ */
  if(!vlclose(villa)){
    fprintf(stderr, "vlclose: %s\n", dperrmsg(dpecode));
    return 1;
  }

  return 0;
}

文字列ã®å‰æ–¹ä¸€è‡´æ¤œç´¢ã‚’行ã†ã‚¢ãƒ—リケーションã®ã‚µãƒ³ãƒ—ルコードを以下ã«ç¤ºã™ã€‚

#include <depot.h>
#include <cabin.h>
#include <villa.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#define DBNAME   "words"
#define PREFIX   "apple"

int main(int argc, char **argv){
  VILLA *villa;
  char *key, *val;

  /* データベースを開ã */
  if(!(villa = vlopen(DBNAME, VL_OWRITER | VL_OCREAT, VL_CMPLEX))){
    fprintf(stderr, "vlopen: %s\n", dperrmsg(dpecode));
    return 1;
  }

  /* レコードを格ç´ã™ã‚‹ */
  if(!vlput(villa, "applet", -1, "little application", -1, VL_DDUP) ||
     !vlput(villa, "aurora", -1, "polar wonderwork", -1, VL_DDUP) ||
     !vlput(villa, "apple", -1, "delicious fruit", -1, VL_DDUP) ||
     !vlput(villa, "amigo", -1, "good friend", -1, VL_DDUP) ||
     !vlput(villa, "apple", -1, "big city", -1, VL_DDUP)){
    fprintf(stderr, "vlput: %s\n", dperrmsg(dpecode));
  }

  /* カーソルを候補ã®å…ˆé ­ã«ç½®ã */
  vlcurjump(villa, PREFIX, -1, VL_JFORWARD);

  /* カーソルを走査ã™ã‚‹ */
  while((key = vlcurkey(villa, NULL)) != NULL){
    if(strstr(key, PREFIX) != key){
      free(key);
      break;
    }
    if(!(val = vlcurval(villa, NULL))){
      fprintf(stderr, "vlcurval: %s\n", dperrmsg(dpecode));
      free(key);
      break;
    }
    printf("%s: %s\n", key, val);
    free(val);
    free(key);
    vlcurnext(villa);
  }

  /* データベースを閉ã˜ã‚‹ */
  if(!vlclose(villa)){
    fprintf(stderr, "vlclose: %s\n", dperrmsg(dpecode));
    return 1;
  }

  return 0;
}

注記

Villaを利用ã—ãŸãƒ—ログラムをビルドã™ã‚‹æ–¹æ³•ã¯ã€Depotã®å ´åˆã¨å…¨ãåŒã˜ã§ã‚る。

gcc -I/usr/local/include -o sample sample.c -L/usr/local/lib -lqdbm

POSIXスレッドを有効ã«ã—ã¦QDBMをビルドã—ãŸå ´åˆã€å¤–部変数 `dpecode' ã¯ã‚¹ãƒ¬ãƒƒãƒ‰å›ºæœ‰ãƒ‡ãƒ¼ã‚¿ã¸ã®å‚ç…§ã¨ã—ã¦æ‰±ã‚れã€Villaã®å„関数ã¯ãƒªã‚¨ãƒ³ãƒˆãƒ©ãƒ³ãƒˆã«ãªã‚‹ã€‚ãã®å ´åˆã€ã‚¹ãƒ¬ãƒƒãƒ‰é–“ã§åŒæ™‚ã«åŒã˜ãƒãƒ³ãƒ‰ãƒ«ã«ã‚¢ã‚¯ã‚»ã‚¹ã—ãªã„é™ã‚Šã¯ã€å„関数ã¯ã‚¹ãƒ¬ãƒƒãƒ‰ã‚»ãƒ¼ãƒ•ã§ã‚る。ãŸã ã—ã€`errno' ã‚„ `malloc' ç­‰ãŒã‚¹ãƒ¬ãƒƒãƒ‰ã‚»ãƒ¼ãƒ•ãªå‡¦ç†ç³»ã§ã‚ã‚‹ã“ã¨ãŒå‰æã¨ãªã‚‹ã€‚

Vista: 拡張上級API

Vistaã¯Villaã‚’æ‹¡å¼µã—ãŸAPIã§ã‚る。VillaãŒ2GB以上ã®ãƒ•ァイルを扱ã†ã“ã¨ãŒã§ããªã„ã¨ã„ã†æ¬ ç‚¹ã‚’補ã†ãŸã‚ã«ã€Vistaã§ã¯Depotã§ã¯ãªãCuriaを用ã„ã¦å†…部データベースを管ç†ã™ã‚‹ã€‚Vistaã¯Villaã¨åŒã˜ãB+木ã®ãƒ‡ãƒ¼ã‚¿æ§‹é€ ã¨ãã®æ“作をæä¾›ã™ã‚‹ãŒã€ãã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã¯ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã§å®Ÿç¾ã•れる。

Vistaを使ã†ã«ã¯ã€`villa.h' ã®ä»£ã‚り㫠`vista.h' をインクルードã™ã‚Œã°ã‚ˆã„。Vistaã¯Villaã®ã‚·ãƒ³ãƒœãƒ«ã‚’マクロã§ã‚ªãƒ¼ãƒãƒ¼ãƒ©ã‚¤ãƒ‰ã—ã¦å®Ÿè£…ã•れã¦ã„ã‚‹ãŸã‚ã€Villaã¨å…¨ãåŒæ§˜ã®APIã§åˆ©ç”¨ã™ã‚‹ã“ã¨ãŒã§ãる。ã™ãªã‚ã¡ã€åŒæ–¹ã®ã‚·ã‚°ãƒãƒãƒ£ã¯å…¨ãåŒã˜ã§ã‚る。ãŸã ã—ã€ãã®å‰¯ä½œç”¨ã¨ã—ã¦ã€Vistaを使ã†ãƒ¢ã‚¸ãƒ¥ãƒ¼ãƒ«ï¼ˆã‚³ãƒ³ãƒ‘イルユニット)ã¯Villaを利用ã™ã‚‹ã“ã¨ãŒã§ããªã„(`villa.h' をインクルードã—ã¦ã¯ãªã‚‰ãªã„)。


Villa用コマンド

Villaã«å¯¾å¿œã™ã‚‹ã‚³ãƒžãƒ³ãƒ‰ãƒ©ã‚¤ãƒ³ã‚¤ãƒ³ã‚¿ãƒ•ェースã¯ä»¥ä¸‹ã®ã‚‚ã®ã§ã‚る。

コマンド `vlmgr' ã¯Villaã‚„ãã®ã‚¢ãƒ—リケーションã®ãƒ‡ãƒãƒƒã‚°ã«å½¹ç«‹ã¤ãƒ„ールã§ã‚る。データベースを更新ã—ãŸã‚Šã€ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®çŠ¶æ…‹ã‚’èª¿ã¹ãŸã‚Šã™ã‚‹æ©Ÿèƒ½ã‚’æŒã¤ã€‚シェルスクリプトã§ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚¢ãƒ—リケーションを作るã®ã«ã‚‚利用ã§ãã‚‹ã€‚ä»¥ä¸‹ã®æ›¸å¼ã§ç”¨ã„る。`name' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹åã€`key' ã¯ãƒ¬ã‚³ãƒ¼ãƒ‰ã®ã‚­ãƒ¼ã€`val' ã¯ãƒ¬ã‚³ãƒ¼ãƒ‰ã®å€¤ã‚’指定ã™ã‚‹ã€‚

vlmgr create [-cz|-cy|-cx] name
データベースファイルを作æˆã™ã‚‹ã€‚
vlmgr put [-kx|-ki] [-vx|-vi|-vf] [-keep|-cat|-dup] name key val
キーã¨å€¤ã«å¯¾å¿œã™ã‚‹ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’追加ã™ã‚‹ã€‚
vlmgr out [-l] [-kx|-ki] name key
キーã«å¯¾å¿œã™ã‚‹ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’削除ã™ã‚‹ã€‚
vlmgr get [-nl] [-l] [-kx|-ki] [-ox] [-n] name key
キーã«å¯¾å¿œã™ã‚‹ãƒ¬ã‚³ãƒ¼ãƒ‰ã®å€¤ã‚’å–å¾—ã—ã¦æ¨™æº–出力ã™ã‚‹ã€‚
vlmgr list [-nl] [-k|-v] [-kx|-ki] [-ox] [-top key] [-bot key] [-gt] [-lt] [-max num] [-desc] name
データベース内ã®å…¨ã¦ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã®ã‚­ãƒ¼ã¨å€¤ã‚’ã‚¿ãƒ–ã¨æ”¹è¡Œã§åŒºåˆ‡ã£ã¦æ¨™æº–出力ã™ã‚‹ã€‚
vlmgr optimize name
データベースを最é©åŒ–ã™ã‚‹ã€‚
vlmgr inform [-nl] name
データベースã®é›‘å¤šãªæƒ…報を出力ã™ã‚‹ã€‚
vlmgr remove name
データベースファイルを削除ã™ã‚‹ã€‚
vlmgr repair [-ki] name
壊れãŸãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルを修復ã™ã‚‹ã€‚
vlmgr exportdb [-ki] name file
å…¨ã¦ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’エンディアンéžä¾å­˜ã®ãƒ‡ãƒ¼ã‚¿ã¨ã—ã¦ãƒ€ãƒ³ãƒ—ã™ã‚‹ã€‚
vlmgr importdb [-ki] name file
エンディアンéžä¾å­˜ãƒ‡ãƒ¼ã‚¿ã‹ã‚‰å…¨ã¦ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’ロードã™ã‚‹ã€‚
vlmgr version
QDBMã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³æƒ…報を標準出力ã™ã‚‹ã€‚

å„オプションã¯ä»¥ä¸‹ã®æ©Ÿèƒ½ã‚’æŒã¤ã€‚

  • -cz : データベースã®ãƒªãƒ¼ãƒ•ã‚’ZLIBã§åœ§ç¸®ã™ã‚‹ã€‚
  • -cy : データベースã®ãƒªãƒ¼ãƒ•ã‚’LZOã§åœ§ç¸®ã™ã‚‹ã€‚
  • -cx : データベースã®ãƒªãƒ¼ãƒ•ã‚’BZIP2ã§åœ§ç¸®ã™ã‚‹ã€‚
  • -l : キーã«ä¸€è‡´ã™ã‚‹å…¨ã¦ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’処ç†å¯¾è±¡ã¨ã™ã‚‹ã€‚
  • -kx : 2æ¡å˜ä½ã®16進数ã«ã‚ˆã‚‹ãƒã‚¤ãƒŠãƒªè¡¨ç¾ã¨ã—㦠`key' を扱ã†ã€‚
  • -ki : 10進数ã«ã‚ˆã‚‹æ•°å€¤è¡¨ç¾ã¨ã—㦠`key' を扱ã†ã€‚
  • -vx : 2æ¡å˜ä½ã®16進数ã«ã‚ˆã‚‹ãƒã‚¤ãƒŠãƒªè¡¨ç¾ã¨ã—㦠`val' を扱ã†ã€‚
  • -vi : 10進数ã«ã‚ˆã‚‹æ•°å€¤è¡¨ç¾ã¨ã—㦠`val' を扱ã†ã€‚
  • -vf : åå‰ãŒ `val' ã®ãƒ•ァイルã®ãƒ‡ãƒ¼ã‚¿ã‚’値ã¨ã—ã¦èª­ã¿è¾¼ã‚€ã€‚
  • -keep : 既存ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã¨ã‚­ãƒ¼ãŒé‡è¤‡æ™‚ã«ä¸Šæ›¸ãã›ãšã«ã‚¨ãƒ©ãƒ¼ã«ã™ã‚‹ã€‚
  • -cat : 既存ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã¨ã‚­ãƒ¼ãŒé‡è¤‡æ™‚ã«å€¤ã‚’末尾ã«è¿½åŠ ã™ã‚‹ã€‚
  • -dup : レコードã®ã‚­ãƒ¼ãŒé‡è¤‡ã™ã‚‹ã®ã‚’許ã™ã€‚
  • -nl : ファイルロックをã‹ã‘ãšã«ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’é–‹ã。
  • -top key : ãƒªã‚¹ãƒˆã®æœ€å°ã®ã‚­ãƒ¼ã‚’指定ã™ã‚‹ã€‚
  • -bot key : ãƒªã‚¹ãƒˆã®æœ€å¤§ã®ã‚­ãƒ¼ã‚’指定ã™ã‚‹ã€‚
  • -gt : 最å°ã®ã‚­ãƒ¼ã‚’リストã«å«ã‚ãªã„。
  • -lt : 最大ã®ã‚­ãƒ¼ã‚’リストã«å«ã‚ãªã„。
  • -max num : リストã™ã‚‹æœ€å¤§æ•°ã‚’指定ã™ã‚‹ã€‚
  • -desc : リストをé™é †ã§è¡Œã†ã€‚
  • -ox : 2æ¡å˜ä½ã®16進数ã«ã‚ˆã‚‹ãƒã‚¤ãƒŠãƒªè¡¨ç¾ã¨ã—ã¦æ¨™æº–出力を行ã†ã€‚
  • -n : æ¨™æº–å‡ºåŠ›ã®æœ«å°¾ã«ä»˜åŠ ã•れる改行文字ã®å‡ºåŠ›ã‚’æŠ‘åˆ¶ã™ã‚‹ã€‚
  • -k : キーã®ã¿ã‚’出力ã™ã‚‹ã€‚
  • -v : 値ã®ã¿ã‚’出力ã™ã‚‹ã€‚

ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯å‡¦ç†ãŒæ­£å¸¸ã«çµ‚了ã™ã‚Œã° 0 ã‚’è¿”ã—ã€ã‚¨ãƒ©ãƒ¼ãŒã‚れã°ãれ以外ã®å€¤ã‚’è¿”ã—ã¦çµ‚了ã™ã‚‹ã€‚環境変数 `QDBMDBGFD' ã®å€¤ã¨ã—ã¦ã€å¤‰æ•° `dpecode' ã®å¤‰æ›´å±¥æ­´ã‚’出力ã™ã‚‹ãƒ•ァイルディスクリプタを指定ã“ã¨ãŒã§ãる。

コマンド `vltest' ã¯Villaã®æ©Ÿèƒ½ãƒ†ã‚¹ãƒˆã‚„性能テストã«ç”¨ã„るツールã§ã‚る。ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã«ã‚ˆã£ã¦ç”Ÿæˆã•れãŸãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルを `vlmgr' ã«ã‚ˆã£ã¦è§£æžã—ãŸã‚Šã€`time' コマンドã«ã‚ˆã£ã¦ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã®å®Ÿè¡Œæ™‚間を計ã£ãŸã‚Šã™ã‚‹ã¨ã‚ˆã„ã€‚ä»¥ä¸‹ã®æ›¸å¼ã§ç”¨ã„る。`name' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹åã€`rnum' ã¯ãƒ¬ã‚³ãƒ¼ãƒ‰æ•°ã€`pnum' ã¯ã‚­ãƒ¼ã®ãƒ‘ターン数を指定ã™ã‚‹ã€‚

vltest write [-int] [-cz|-cy|-cx] [-tune lrecmax nidxmax lcnum ncnum] [-fbp num] name rnum
`00000001'ã€`00000002' ã®ã‚ˆã†ã«å¤‰åŒ–ã™ã‚‹8ãƒã‚¤ãƒˆã®ã‚­ãƒ¼ã¨é©å½“ãª8ãƒã‚¤ãƒˆã®å€¤ã‚’連続ã—ã¦ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«è¿½åŠ ã™ã‚‹ã€‚
vltest read [-int] [-vc] name
上記ã§ç”Ÿæˆã—ãŸãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®å…¨ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’検索ã™ã‚‹ã€‚
vltest rdup [-int] [-cz|-cy|-cx] [-cc] [-tune lrecmax nidxmax lcnum ncnum] [-fbp num] name rnum pnum
キーãŒã‚る程度é‡è¤‡ã™ã‚‹ã‚ˆã†ã«ãƒ¬ã‚³ãƒ¼ãƒ‰ã®è¿½åŠ ã‚’è¡Œã„ã€é‡è¤‡ãƒ¢ãƒ¼ãƒ‰ã§å‡¦ç†ã™ã‚‹ã€‚
vltest combo [-cz|-cy|-cx] name
å„種æ“作ã®çµ„ã¿åˆã‚ã›ãƒ†ã‚¹ãƒˆã‚’行ã†ã€‚
vltest wicked [-cz|-cy|-cx] name rnum
å„種更新æ“作を無作為ã«é¸æŠžã—ã¦å®Ÿè¡Œã™ã‚‹ã€‚

å„オプションã¯ä»¥ä¸‹ã®æ©Ÿèƒ½ã‚’æŒã¤ã€‚

  • -int : `int' åž‹ã®ã‚ªãƒ–ジェクトをキーã¨å€¤ã«ç”¨ã„ã€æ¯”較関数もãれã«åˆã‚ã›ã‚‹ã€‚
  • -cz : データベースã®ãƒªãƒ¼ãƒ•ã‚’ZLIBã§åœ§ç¸®ã™ã‚‹ã€‚
  • -cy : データベースã®ãƒªãƒ¼ãƒ•ã‚’LZOã§åœ§ç¸®ã™ã‚‹ã€‚
  • -cx : データベースã®ãƒªãƒ¼ãƒ•ã‚’BZIP2ã§åœ§ç¸®ã™ã‚‹ã€‚
  • -vc : æ®ç™ºæ€§ã‚­ãƒ£ãƒƒã‚·ãƒ¥ã‚’å‚ç…§ã™ã‚‹ã€‚
  • -cc : 連çµãƒ¢ãƒ¼ãƒ‰ã¨é‡è¤‡ãƒ¢ãƒ¼ãƒ‰ã‚’無作為ã«é¸æŠžã™ã‚‹ã€‚
  • -tune lrecmax nidxmax lcnum ncnum : 性能パラメータを指定ã™ã‚‹ã€‚
  • -fbp num : フリーブロックプールã®ã‚µã‚¤ã‚ºã‚’指定ã™ã‚‹ã€‚
  • -c : Cabinã®ãƒžãƒƒãƒ—を使ã£ã¦æ¯”較テストを行ã†ã€‚

ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯å‡¦ç†ãŒæ­£å¸¸ã«çµ‚了ã™ã‚Œã° 0 ã‚’è¿”ã—ã€ã‚¨ãƒ©ãƒ¼ãŒã‚れã°ãれ以外ã®å€¤ã‚’è¿”ã—ã¦çµ‚了ã™ã‚‹ã€‚環境変数 `QDBMDBGFD' ã®å€¤ã¨ã—ã¦ã€å¤‰æ•° `dpecode' ã®å¤‰æ›´å±¥æ­´ã‚’出力ã™ã‚‹ãƒ•ァイルディスクリプタを指定ã“ã¨ãŒã§ãる。

コマンド `vltsv' ã¯ã‚¿ãƒ–区切りã§ã‚­ãƒ¼ã¨å€¤ã‚’表ç¾ã—ãŸè¡Œã‹ã‚‰ãªã‚‹TSVファイルã¨Villaã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’相互変æ›ã™ã‚‹ã€‚ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯ã€QDBMã®ä»–ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã‚„ä»–ã®DBMã¨ã®é–“ã§ãƒ‡ãƒ¼ã‚¿ã®äº¤æ›ã‚’行ã†éš›ã«å½¹ç«‹ã¤ã€‚ã¾ãŸã€ãƒã‚¤ãƒˆã‚ªãƒ¼ãƒ€ã®é•ã†ã‚·ã‚¹ãƒ†ãƒ ã®é–“ã§ãƒ‡ãƒ¼ã‚¿ã‚’交æ›ã™ã‚‹éš›ã«ã‚‚役立ã¤ã€‚ä»¥ä¸‹ã®æ›¸å¼ã§ç”¨ã„る。`name' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹åを指定ã™ã‚‹ã€‚`export' サブコマンドã§ã¯TSVã®ãƒ‡ãƒ¼ã‚¿ã¯æ¨™æº–入力ã‹ã‚‰èª­ã¿è¾¼ã‚€ã€‚`import' サブコマンドã§ã¯TSVã®ãƒ‡ãƒ¼ã‚¿ãŒæ¨™æº–å‡ºåŠ›ã«æ›¸ã出ã•れる。

vltsv import [-bin] name
TSVファイルを読ã¿è¾¼ã‚“ã§ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’作æˆã™ã‚‹ã€‚
vltsv export [-bin] name
データベースã®å…¨ã¦ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’TSVファイルã¨ã—ã¦å‡ºåŠ›ã™ã‚‹ã€‚

å„オプションã¯ä»¥ä¸‹ã®æ©Ÿèƒ½ã‚’æŒã¤ã€‚

  • -bin : Base64å½¢å¼ã§ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’扱ã†ã€‚

ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯å‡¦ç†ãŒæ­£å¸¸ã«çµ‚了ã™ã‚Œã° 0 ã‚’è¿”ã—ã€ã‚¨ãƒ©ãƒ¼ãŒã‚れã°ãれ以外ã®å€¤ã‚’è¿”ã—ã¦çµ‚了ã™ã‚‹ã€‚

Villaã®ã‚³ãƒžãƒ³ãƒ‰ç¾¤ã‚’駆使ã™ã‚‹ã¨ã€ç°¡å˜ãªãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚·ã‚¹ãƒ†ãƒ ãŒæ§‹ç¯‰ã§ãる。例ãˆã° `/etc/password' をユーザåã§æ¤œç´¢ã™ã‚‹ãŸã‚ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’作æˆã™ã‚‹ã«ã¯ã€ä»¥ä¸‹ã®ã‚ˆã†ã«ã™ã‚‹ã€‚

cat /etc/passwd | tr ':' '\t' | vltsv import casket

ãã—ã¦ã€`mikio' ã¨ã„ã†ãƒ¦ãƒ¼ã‚¶ã®æƒ…報をå–り出ã™ã«ã¯ã€ä»¥ä¸‹ã®ã‚ˆã†ã«ã™ã‚‹ã€‚

vlmgr get casket mikio

ã“れらã®ã‚³ãƒžãƒ³ãƒ‰ã¨åŒç­‰ã®æ©Ÿèƒ½ã‚’Villaã®APIを用ã„ã¦å®Ÿè£…ã™ã‚‹ã“ã¨ã‚‚容易ã§ã‚る。

コマンド `qmttest' ã¯Depotã¨Curiaã¨Villaã®ãƒžãƒ«ãƒã‚¹ãƒ¬ãƒƒãƒ‰ã«ãŠã‘る安全性を調査ã™ã‚‹ã€‚ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯POSIXスレッドを有効ã«ã—ã¦QDBMをビルドã—ãŸå ´åˆã«ã®ã¿ãƒžãƒ«ãƒã‚¹ãƒ¬ãƒƒãƒ‰ã§å‹•作ã™ã‚‹ã€‚ä»¥ä¸‹ã®æ›¸å¼ã§ç”¨ã„る。`name' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹åã®æŽ¥é ­è¾žã‚’æŒ‡å®šã™ã‚‹ã€‚`rnum' ã¯å„ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«æ›¸ã込むレコード数を指定ã™ã‚‹ã€‚`tnum' ã¯ã‚¹ãƒ¬ãƒƒãƒ‰æ•°ã‚’指定ã™ã‚‹ã€‚

qmttest name rnum tnum
マルãƒã‚¹ãƒ¬ãƒƒãƒ‰ã«ãŠã‘る安全性を調査ã™ã‚‹ã€‚

ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯å‡¦ç†ãŒæ­£å¸¸ã«çµ‚了ã™ã‚Œã° 0 ã‚’è¿”ã—ã€ã‚¨ãƒ©ãƒ¼ãŒã‚れã°ãれ以外ã®å€¤ã‚’è¿”ã—ã¦çµ‚了ã™ã‚‹ã€‚


Odeum: 転置API

概è¦

Odeumã¯è»¢ç½®ã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹ã‚’扱ã†APIã§ã‚る。転置インデックスã¨ã¯ã€æ¯é›†å›£ã®æ–‡æ›¸ç¾¤ã«å«ã¾ã‚Œã‚‹èªžã‚’抽出ã—ã¦ã€å„語をキーã¨ã—ã€ãã®èªžã‚’å«ã‚€æ–‡æ›¸ã®ãƒªã‚¹ãƒˆã‚’検索ã™ã‚‹ãŸã‚ã®ãƒ‡ãƒ¼ã‚¿æ§‹é€ ã§ã‚る。転置インデックスを用ã„ã‚‹ã¨ã€å…¨æ–‡æ¤œç´¢ã‚·ã‚¹ãƒ†ãƒ ã‚’容易ã«å®Ÿç¾ã™ã‚‹ã“ã¨ãŒã§ãる。Odeumã¯æ–‡æ›¸ã‚’語や属性ã®é›†åˆã¨ã—ã¦æ‰±ã†ãŸã‚ã®æŠ½è±¡ãƒ‡ãƒ¼ã‚¿åž‹ã‚’æä¾›ã™ã‚‹ã€‚ãれã¯ã€å„アプリケーションãŒOdeumã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«æ–‡æ›¸ã‚’æ ¼ç´ã™ã‚‹éš›ã‚„ã€ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‹ã‚‰æ–‡æ›¸ã‚’検索ã™ã‚‹éš›ã«ç”¨ã„られる。

Odeumã¯å…ƒæ¥ã®æ–‡æ›¸ãƒ‡ãƒ¼ã‚¿ã‹ã‚‰ãƒ†ã‚­ã‚¹ãƒˆã‚’抽出ã™ã‚‹æ–¹æ³•ã¯æä¾›ã—ãªã„。ãれã¯ã‚¢ãƒ—リケーションãŒå®Ÿè£…ã™ã‚‹å¿…è¦ãŒã‚る。Odeumã¯ãƒ†ã‚­ã‚¹ãƒˆã‚’分解ã—ã¦èªžç¾¤ã‚’抽出ã™ã‚‹ãƒ¦ãƒ¼ãƒ†ã‚£ãƒªãƒ†ã‚£ã‚’æä¾›ã™ã‚‹ãŒã€ãれã¯ç©ºç™½ã§èªžãŒåˆ†å‰²ã•れる英語ãªã©ã®è¨€èªžã‚’指å‘ã—ã¦ã„る。形態素解æžã‚„N-gramè§£æžãŒå¿…è¦ãªæ—¥æœ¬èªžãªã©ã®è¨€èªžã‚’扱ã†éš›ã‚„ã€ã‚¹ãƒ†ãƒŸãƒ³ã‚°ãªã©ã®ã‚ˆã‚Šé«˜åº¦ãªè‡ªç„¶è¨€èªžå‡¦ç†ã‚’行ã†éš›ã«ã¯ã€ã‚¢ãƒ—リケーションã¯ç‹¬è‡ªã®è§£æžæ–¹æ³•ã‚’é©ç”¨ã™ã‚‹ã“ã¨ãŒã§ãã‚‹ã€‚æ¤œç´¢çµæžœã¯æ–‡æ›¸ã®ID番å·ã¨ãã®ã‚¹ã‚³ã‚¢ã‚’メンãƒã«æŒã¤æ§‹é€ ä½“ã‚’è¦ç´ ã¨ã™ã‚‹é…列ã¨ã—ã¦å¾—られる。複数ã®èªžã‚’用ã„ã¦æ¤œç´¢ã‚’行ã†ãŸã‚ã«ã€Odeumã¯çµæžœã®é…列ã®é›†åˆæ¼”算を行ã†ãƒ¦ãƒ¼ãƒ†ã‚£ãƒªãƒ†ã‚£ã‚’æä¾›ã™ã‚‹ã€‚

Odeumã¯Curiaã¨Cabinã¨Villaを基盤ã¨ã—ã¦å®Ÿè£…ã•れる。Odeumã§ã¯ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªåを指定ã—ã¦ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’構築ã™ã‚‹ã€‚特定ã®ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã®ç›´ä¸‹ã«Curiaã‚„Villaã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’構築ã™ã‚‹ã€‚例ãˆã°ã€`casket' ã¨ã„ã†åå‰ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’作æˆã™ã‚‹å ´åˆã€`casket/docs'ã€`casket/index' ãŠã‚ˆã³ `casket/rdocs' ãŒç”Ÿæˆã•れる。`docs' ã¯Curiaã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã§ã‚ã‚‹ã€‚ã‚­ãƒ¼ã¯æ–‡æ›¸ã®ID番å·ã§ã‚りã€å€¤ã¯URIç­‰ã®æ–‡æ›¸å±žæ€§ã§ã‚る。`index' ã¯Curiaã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã§ã‚る。キーã¯èªžã®æ­£è¦å½¢ã§ã‚りã€å€¤ã¯ãã®èªžã‚’å«ã‚€æ–‡æ›¸ã®ID番å·ã¨ãã®ã‚¹ã‚³ã‚¢ã‚’è¦ç´ ã¨ã™ã‚‹é…列ã§ã‚る。`rdocs' ã¯Villaã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルã§ã‚ã‚‹ã€‚ã‚­ãƒ¼ã¯æ–‡æ›¸ã®URIã§ã‚りã€å€¤ã¯æ–‡æ›¸ã®ID番å·ã§ã‚る。

Odeumを使ã†ãŸã‚ã«ã¯ã€`depot.h' 㨠`cabin.h' 㨠`odeum.h' 㨠`stdlib.h' をインクルードã™ã¹ãã§ã‚る。通常ã€ã‚½ãƒ¼ã‚¹ãƒ•ァイルã®å†’頭付近ã§ä»¥ä¸‹ã®è¨˜è¿°ã‚’行ã†ã€‚

#include <depot.h>
#include <cabin.h>
#include <odeum.h>
#include <stdlib.h>

Odeumã§ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’扱ã†éš›ã«ã¯ã€`ODEUM' åž‹ã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’ãƒãƒ³ãƒ‰ãƒ«ã¨ã—ã¦ç”¨ã„る。ãƒãƒ³ãƒ‰ãƒ«ã¯ã€é–¢æ•° `odopen' ã§é–‹ãã€é–¢æ•° `odclose' ã§é–‰ã˜ã‚‹ã€‚ãƒãƒ³ãƒ‰ãƒ«ã®ãƒ¡ãƒ³ãƒã‚’直接å‚ç…§ã™ã‚‹ã“ã¨ã¯æŽ¨å¥¨ã•れãªã„。データベースã«è‡´å‘½çš„ãªã‚¨ãƒ©ãƒ¼ãŒèµ·ããŸå ´åˆã¯ã€ä»¥å¾Œãã®ãƒãƒ³ãƒ‰ãƒ«ã«å¯¾ã™ã‚‹ `odclose' を除ãå…¨ã¦ã®æ“作ã¯ä½•ã‚‚ã›ãšã«ã‚¨ãƒ©ãƒ¼ã‚’è¿”ã™ã€‚ã²ã¨ã¤ã®ãƒ—ロセスã§è¤‡æ•°ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ã‚¡ã‚¤ãƒ«ã‚’åŒæ™‚ã«åˆ©ç”¨ã™ã‚‹ã“ã¨ã¯å¯èƒ½ã§ã‚ã‚‹ãŒã€åŒã˜ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルã®è¤‡æ•°ã®ãƒãƒ³ãƒ‰ãƒ«ã‚’利用ã—ã¦ã¯ãªã‚‰ãªã„。

儿–‡æ›¸ã‚’扱ã†éš›ã«ã¯ã€`ODDOC' åž‹ã¸ã®ãƒã‚¤ãƒ³ã‚¿ã‚’ãƒãƒ³ãƒ‰ãƒ«ã¨ã—ã¦ç”¨ã„る。ãƒãƒ³ãƒ‰ãƒ«ã¯ã€é–¢æ•° `oddocopen' ã§é–‹ãã€é–¢æ•° `oddocclose' ã§é–‰ã˜ã‚‹ã€‚ãƒãƒ³ãƒ‰ãƒ«ã®ãƒ¡ãƒ³ãƒã‚’直接å‚ç…§ã™ã‚‹ã“ã¨ã¯æŽ¨å¥¨ã•れãªã„。文書ã¯å±žæ€§ã¨èªžã®é›†åˆã‹ã‚‰ãªã‚‹ã€‚èªžã¯æ­£è¦å½¢ã¨å‡ºç¾å½¢ã®ãƒšã‚¢ã¨ã—ã¦è¡¨ç¾ã•れる。

Odeumã§ã‚‚Depotã¨åŒã˜ã外部変数 `dpecode' ã«ç›´å‰ã®ã‚¨ãƒ©ãƒ¼ã‚³ãƒ¼ãƒ‰ãŒè¨˜éŒ²ã•れる。エラーコードã«å¯¾å¿œã™ã‚‹ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸æ–‡å­—列を得るã«ã¯ã€é–¢æ•° `dperrmsg' を用ã„る。

API

æ¤œç´¢çµæžœã‚’扱ã†ãŸã‚ã«ã¯ã€`ODPAIR' åž‹ã®æ§‹é€ ä½“を用ã„る。

typedef struct { int id; int score; } ODPAIR;
`id' ã¯æ–‡æ›¸ã®ID番å·ã§ã‚る。`score' ã¯æ–‡æ›¸ã«å«ã¾ã‚Œã‚‹æ¤œç´¢èªžã®æ•°ã‚’å…ƒã«ç®—出ã•れるスコアã§ã‚る。

データベースã®ãƒãƒ³ãƒ‰ãƒ«ã‚’作æˆã™ã‚‹ã«ã¯ã€é–¢æ•° `odopen' を用ã„る。

ODEUM *odopen(const char *name, int omode);
`name' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã®åå‰ã‚’指定ã™ã‚‹ã€‚`omode' ã¯æŽ¥ç¶šãƒ¢ãƒ¼ãƒ‰ã‚’æŒ‡å®šã—ã€`OD_OREADER' ãªã‚‰ãƒªãƒ¼ãƒ€ã€`OD_OWRITER' ãªã‚‰ãƒ©ã‚¤ã‚¿ã¨ãªã‚‹ã€‚`OD_OWRITER' ã®å ´åˆã€`OD_OCREAT' ã¾ãŸã¯ `OD_OTRUNC' ã¨ã®ãƒ“ット論ç†å’Œã«ã™ã‚‹ã“ã¨ãŒã§ãる。`OD_OCREAT' ã¯ãƒ•ァイルãŒç„¡ã„å ´åˆã«æ–°è¦ä½œæˆã™ã‚‹ã“ã¨ã‚’指示ã—ã€`OD_OTRUNC' ã¯ãƒ•ァイルãŒå­˜åœ¨ã—ã¦ã‚‚作り直ã™ã“ã¨ã‚’指示ã™ã‚‹ã€‚`OD_OREADER' 㨠`OD_OWRITER' ã®ä¸¡æ–¹ã§ `OD_ONOLCK' ã‹ `OD_OLCKNB' ã¨ã®ãƒ“ット論ç†å’Œã«ã™ã‚‹ã“ã¨ãŒã§ãã‚‹ãŒã€å‰è€…ã¯ãƒ•ァイルロックをã‹ã‘ãšã«ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’é–‹ãã“ã¨ã‚’指示ã—ã€å¾Œè€…ã¯ãƒ–ロックã›ãšã«ãƒ­ãƒƒã‚¯ã‚’ã‹ã‘ã‚‹ã“ã¨ã‚’指示ã™ã‚‹ã€‚戻り値ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã§ã‚ã‚‹ã‹ã€ã‚¨ãƒ©ãƒ¼ãªã‚‰ `NULL' ã§ã‚ã‚‹ã€‚ãƒ©ã‚¤ã‚¿ï¼ˆèª­ã¿æ›¸ã両用モード)ã§ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルを開ãéš›ã«ã¯ãã®ãƒ•ァイルã«å¯¾ã—ã¦æŽ’ä»–ãƒ­ãƒƒã‚¯ãŒã‹ã‘られã€ãƒªãƒ¼ãƒ€ï¼ˆèª­ã¿è¾¼ã¿å°‚用モード)ã§é–‹ãéš›ã«ã¯å…±æœ‰ãƒ­ãƒƒã‚¯ãŒã‹ã‘られる。ãã®éš›ã«ã¯è©²å½“ã®ãƒ­ãƒƒã‚¯ãŒã‹ã‘られるã¾ã§åˆ¶å¾¡ãŒãƒ–ロックã™ã‚‹ã€‚`OD_ONOLCK' を使ã†å ´åˆã€ã‚¢ãƒ—ãƒªã‚±ãƒ¼ã‚·ãƒ§ãƒ³ãŒæŽ’ä»–åˆ¶å¾¡ã®è²¬ä»»ã‚’è² ã†ã€‚

データベースã¨ã®æŽ¥ç¶šã‚’é–‰ã˜ã¦ãƒãƒ³ãƒ‰ãƒ«ã‚’破棄ã™ã‚‹ã«ã¯ã€é–¢æ•° `odclose' を用ã„る。

int odclose(ODEUM *odeum);
`odeum' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰çœŸã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰å½ã§ã‚ã‚‹ã€‚ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®æ›´æ–°å†…容ã¯ã€æŽ¥ç¶šã‚’é–‰ã˜ãŸæ™‚点ã§åˆã‚ã¦ãƒ•ァイルã¨åŒæœŸã•れる。ライタã§ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’é–‹ã„ãŸå ´åˆã€é©åˆ‡ã«æŽ¥ç¶šã‚’é–‰ã˜ãªã„ã¨ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãŒç ´å£Šã•れる。閉ã˜ãŸãƒãƒ³ãƒ‰ãƒ«ã®é ˜åŸŸã¯è§£æ”¾ã•れるã®ã§ã€ä»¥å¾Œã¯åˆ©ç”¨ã§ããªããªã‚‹ã€‚

文書を追加ã™ã‚‹ã«ã¯ã€é–¢æ•° `odput' を用ã„る。

int odput(ODEUM *odeum, const ODDOC *doc, int wmax, int over);
`odeum' ã¯ãƒ©ã‚¤ã‚¿ã§æŽ¥ç¶šã—ãŸãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`doc' ã¯æ–‡æ›¸ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`wmax' ã¯æ–‡æ›¸ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«æ ¼ç´ã™ã‚‹èªžã®æœ€å¤§æ•°ã‚’指定ã™ã‚‹ãŒã€è² æ•°ãªã‚‰ç„¡åˆ¶é™ã¨ãªã‚‹ã€‚`over' ã¯é‡è¤‡ã—ãŸæ–‡æ›¸ã®ä¸Šæ›¸ãを行ã†ã‹å¦ã‹ã‚’指定ã™ã‚‹ã€‚ãれãŒå½ã§æ–‡æ›¸ã®URIãŒé‡è¤‡ã—ãŸå ´åˆã¯ã‚¨ãƒ©ãƒ¼ã¨ãªã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰çœŸã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰å½ã§ã‚る。

URIã§æŒ‡å®šã—ãŸæ–‡æ›¸ã‚’削除ã™ã‚‹ã«ã¯ã€é–¢æ•° `odout' を用ã„る。

int odout(ODEUM *odeum, const char *uri);
`odeum' ã¯ãƒ©ã‚¤ã‚¿ã§æŽ¥ç¶šã—ãŸãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`uri' ã¯æ–‡æ›¸ã®URIã®æ–‡å­—列を指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰çœŸã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰å½ã§ã‚る。該当ã™ã‚‹æ–‡æ›¸ãŒãªã„å ´åˆã‚‚å½ã‚’è¿”ã™ã€‚

ID番å·ã§æŒ‡å®šã—ãŸæ–‡æ›¸ã‚’削除ã™ã‚‹ã«ã¯ã€é–¢æ•° `odoutbyid' を用ã„る。

int odoutbyid(ODEUM *odeum, int id);
`odeum' ã¯ãƒ©ã‚¤ã‚¿ã§æŽ¥ç¶šã—ãŸãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`id' ã¯æ–‡æ›¸ã®ID番å·ã‚’指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰çœŸã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰å½ã§ã‚る。該当ã™ã‚‹æ–‡æ›¸ãŒãªã„å ´åˆã‚‚å½ã‚’è¿”ã™ã€‚

URIã§æŒ‡å®šã—ãŸæ–‡æ›¸ã‚’å–å¾—ã™ã‚‹ã«ã¯ã€é–¢æ•° `odget' を用ã„る。

ODDOC *odget(ODEUM *odeum, const char *uri);
`odeum' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`uri' ã¯æ–‡æ›¸ã®URIã®æ–‡å­—列を指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰è©²å½“ã®æ–‡æ›¸ã®ãƒãƒ³ãƒ‰ãƒ«ã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰ `NULL' ã§ã‚ã‚‹ã€‚è©²å½“ã®æ–‡æ›¸ãŒãªã„å ´åˆã‚‚ `NULL' ã‚’è¿”ã™ã€‚戻り値ã®ãƒãƒ³ãƒ‰ãƒ«ã¯ã€é–¢æ•° `oddocopen' ã§é–‹ã‹ã‚Œã‚‹ã®ã§ã€ä¸è¦ã«ãªã£ãŸã‚‰ `oddocclose' ã§é–‰ã˜ã‚‹ã¹ãã§ã‚る。

ID番å·ã§æŒ‡å®šã—ãŸæ–‡æ›¸ã‚’å–å¾—ã™ã‚‹ã«ã¯ã€é–¢æ•° `odgetbyid' を用ã„る。

ODDOC *odgetbyid(ODEUM *odeum, int id);
`odeum' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`id' ã¯æ–‡æ›¸ã®ID番å·ã‚’指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰è©²å½“ã®æ–‡æ›¸ã®ãƒãƒ³ãƒ‰ãƒ«ã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰ `NULL' ã§ã‚ã‚‹ã€‚è©²å½“ã®æ–‡æ›¸ãŒãªã„å ´åˆã‚‚ `NULL' ã‚’è¿”ã™ã€‚戻り値ã®ãƒãƒ³ãƒ‰ãƒ«ã¯ã€é–¢æ•° `oddocopen' ã§é–‹ã‹ã‚Œã‚‹ã®ã§ã€ä¸è¦ã«ãªã£ãŸã‚‰ `oddocclose' ã§é–‰ã˜ã‚‹ã¹ãã§ã‚る。

URIã§æŒ‡å®šã—ãŸæ–‡æ›¸ã®IDã‚’å–å¾—ã™ã‚‹ã«ã¯ã€é–¢æ•° `odgetidbyuri' を用ã„る。

int odgetidbyuri(ODEUM *odeum, const char *uri);
`odeum' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`uri' ã¯æ–‡æ›¸ã®URIã®æ–‡å­—列を指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰è©²å½“ã®æ–‡æ›¸ã®IDã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰ -1 ã§ã‚ã‚‹ã€‚è©²å½“ã®æ–‡æ›¸ãŒãªã„å ´åˆã‚‚ -1 ã‚’è¿”ã™ã€‚

ID番å·ã§æŒ‡å®šã—ãŸæ–‡æ›¸ãŒå­˜åœ¨ã—ã¦ã„ã‚‹ã‹èª¿ã¹ã‚‹ã«ã¯ã€é–¢æ•° `odcheck' を用ã„る。

int odcheck(ODEUM *odeum, int id);
`odeum' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`id' ã¯æ–‡æ›¸ã®ID番å·ã‚’指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ–‡æ›¸ãŒå­˜åœ¨ã™ã‚Œã°çœŸã€ãã†ã§ãªã‘れã°å½ã§ã‚る。

転置インデックスを検索ã—ã¦ç‰¹å®šã®èªžã‚’å«ã‚€æ–‡æ›¸ç¾¤ã‚’知るã«ã¯ã€é–¢æ•° `odsearch' を用ã„る。

ODPAIR *odsearch(ODEUM *odeum, const char *word, int max, int *np);
`odeum' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`word' ã¯æ¤œç´¢èªžã‚’指定ã™ã‚‹ã€‚`max' ã¯å–ã‚Šå‡ºã™æ–‡æ›¸ã®æœ€å¤§æ•°ã‚’指定ã™ã‚‹ã€‚`np' ã®å‚ç…§å…ˆã«ã¯ã€æˆ»ã‚Šå€¤ã®é…列ã®è¦ç´ æ•°ãŒæ ¼ç´ã•ã‚Œã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰é…列ã¸ã®ãƒã‚¤ãƒ³ã‚¿ã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰ `NULL' ã§ã‚る。ãã®é…列ã®å„è¦ç´ ã¯æ–‡æ›¸ã®ID番å·ã¨ã‚¹ã‚³ã‚¢ã®ãƒšã‚¢ã§ã‚りã€ã‚¹ã‚³ã‚¢ã®é™é †ã§ä¸¦ã¹ã‚‰ã‚Œã‚‹ã€‚検索語ã«è©²å½“ã™ã‚‹æ–‡æ›¸ãŒä¸€ã¤ã‚‚ãªã‹ã£ãŸã¨ã—ã¦ã‚‚エラーã«ã¯ãªã‚‰ãšã«ã€ç©ºã®é…列を返ã™ã€‚戻り値ã®é ˜åŸŸã¯ `malloc' ã§ç¢ºä¿ã•れるã®ã§ã€ä¸è¦ã«ãªã£ãŸã‚‰ `free' ã§è§£æ”¾ã™ã‚‹ã¹ãã§ã‚る。é…列ã®å„è¦ç´ ã«ã¯æ—¢ã«å‰Šé™¤ã•ã‚ŒãŸæ–‡æ›¸ã®ãƒ‡ãƒ¼ã‚¿ã‚‚å«ã¾ã‚Œã‚‹ã“ã¨ã«æ³¨æ„ã™ã¹ãã§ã‚る。

特定ã®èªžã‚’å«ã‚€æ–‡æ›¸ã®æ•°ã‚’知るã«ã¯ã€é–¢æ•° `odsearchdnum' を用ã„る。

int odsearchdnum(ODEUM *odeum, const char *word);
`odeum' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`word' ã¯æ¤œç´¢èªžã‚’指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰æ¤œç´¢èªžã‚’å«ã‚€æ–‡æ›¸ã®æ•°ã§ã‚りã€è©²å½“ãŒãªã„å ´åˆã‚„エラーã®å ´åˆã¯ -1 ã§ã‚る。ã“ã®é–¢æ•°ã¯è»¢ç½®ã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹ã®å®Ÿãƒ‡ãƒ¼ã‚¿ã‚’読ã¿è¾¼ã¾ãªã„ã®ã§åŠ¹çŽ‡ãŒã‚ˆã„。

データベースã®ã‚¤ãƒ†ãƒ¬ãƒ¼ã‚¿ã‚’åˆæœŸåŒ–ã™ã‚‹ã«ã¯ã€é–¢æ•° `oditerinit' を用ã„る。

int oditerinit(ODEUM *odeum);
`odeum' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰çœŸã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰å½ã§ã‚る。イテレータã¯ã€ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«æ ¼ç´ã•れãŸå…¨ã¦ã®æ–‡æ›¸ã‚’å‚ç…§ã™ã‚‹ãŸã‚ã«ç”¨ã„られる。

データベースã®ã‚¤ãƒ†ãƒ¬ãƒ¼ã‚¿ã‹ã‚‰æ¬¡ã®æ–‡æ›¸ã‚’å–り出ã™ã«ã¯ã€é–¢æ•° `oditernext' を用ã„る。

ODDOC *oditernext(ODEUM *odeum);
`odeum' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰æ–‡æ›¸ãƒãƒ³ãƒ‰ãƒ«ã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰ `NULL' ã§ã‚ã‚‹ã€‚ã‚¤ãƒ†ãƒ¬ãƒ¼ã‚¿ãŒæœ€å¾Œã¾ã§ãã¦è©²å½“ã®æ–‡æ›¸ãŒãªã„å ´åˆã‚‚ `NULL' ã‚’è¿”ã™ã€‚ã“ã®é–¢æ•°ã‚’繰り返ã—ã¦å‘¼ã¶ã“ã¨ã«ã‚ˆã£ã¦å…¨ã¦ã®æ–‡æ›¸ã‚’一度ãšã¤å‚ç…§ã™ã‚‹ã“ã¨ãŒã§ãる。ãŸã ã—ã€ç¹°ã‚Šè¿”ã—ã®é–“ã«ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®æ›´æ–°ãŒã‚ã£ãŸå ´åˆã¯ãã®é™ã‚Šã§ã¯ãªã„。ãªãŠã€å–り出ã™ãƒ¬ã‚³ãƒ¼ãƒ‰ã®é †åºã¯åˆ¶å¾¡ã§ããšã€æ ¼ç´ã—ãŸé †ç•ªã§ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’å–り出ã›ã‚‹ã¨ã¯é™ã‚‰ãªã„。戻り値ã®ãƒãƒ³ãƒ‰ãƒ«ã¯ã€é–¢æ•° `oddocopen' ã§é–‹ã‹ã‚Œã‚‹ã®ã§ã€ä¸è¦ã«ãªã£ãŸã‚‰ `oddocclose' ã§é–‰ã˜ã‚‹ã¹ãã§ã‚る。

データベースを更新ã—ãŸå†…容をファイルã¨ãƒ‡ãƒã‚¤ã‚¹ã«åŒæœŸã•ã›ã‚‹ã«ã¯ã€é–¢æ•° `odsync' を用ã„る。

int odsync(ODEUM *odeum);
`odeum' ã¯ãƒ©ã‚¤ã‚¿ã§æŽ¥ç¶šã—ãŸãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰çœŸã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰å½ã§ã‚る。ã“ã®é–¢æ•°ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’é–‰ã˜ãªã„ã†ã¡ã«åˆ¥ãƒ—ロセスã«ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã‚’利用ã•ã›ã‚‹å ´åˆã«å½¹ç«‹ã¤ã€‚

データベースを最é©åŒ–ã™ã‚‹ã«ã¯ã€é–¢æ•° `odoptimize' を用ã„る。

int odoptimize(ODEUM *odeum);
`odeum' ã¯ãƒ©ã‚¤ã‚¿ã§æŽ¥ç¶šã—ãŸãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰çœŸã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰å½ã§ã‚る。転置インデックスã«ãŠã‘る削除ã•ã‚ŒãŸæ–‡æ›¸ã®è¦ç´ ã¯å‰Šé™¤ã•れる。

データベースã®åå‰ã‚’å¾—ã‚‹ã«ã¯ã€é–¢æ•° `odname' を用ã„る。

char *odname(ODEUM *odeum);
`odeum' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰åå‰ã‚’æ ¼ç´ã—ãŸé ˜åŸŸã¸ã®ãƒã‚¤ãƒ³ã‚¿ã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰ `NULL' ã§ã‚る。戻り値ã®é ˜åŸŸã¯ `malloc' ã§ç¢ºä¿ã•れるã®ã§ã€ä¸è¦ã«ãªã£ãŸã‚‰ `free' ã§è§£æ”¾ã™ã‚‹ã¹ãã§ã‚る。

データベースファイルã®ã‚µã‚¤ã‚ºã®åˆè¨ˆã‚’å¾—ã‚‹ã«ã¯ã€é–¢æ•° `odfsiz' を用ã„る。

double odfsiz(ODEUM *odeum);
`odeum' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルã®ã‚µã‚¤ã‚ºã®åˆè¨ˆã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰ -1.0 ã§ã‚る。

転置インデックス内ã®ãƒã‚±ãƒƒãƒˆé…列ã®è¦ç´ æ•°ã®åˆè¨ˆã‚’å¾—ã‚‹ã«ã¯ã€é–¢æ•° `odbnum' を用ã„る。

int odbnum(ODEUM *odeum);
`odeum' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰ãƒã‚±ãƒƒãƒˆé…列ã®è¦ç´ æ•°ã®åˆè¨ˆã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰ -1 ã§ã‚る。

転置インデックス内ã®ãƒã‚±ãƒƒãƒˆé…列ã®åˆ©ç”¨æ¸ˆã¿ã®è¦ç´ æ•°ã®åˆè¨ˆã‚’å¾—ã‚‹ã«ã¯ã€é–¢æ•° `odbusenum' を用ã„る。

int odbusenum(ODEUM *odeum);
`odeum' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰ãƒã‚±ãƒƒãƒˆé…列ã®åˆ©ç”¨æ¸ˆã¿ã®è¦ç´ æ•°ã®åˆè¨ˆã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰ -1 ã§ã‚る。

ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«æ ¼ç´ã•ã‚ŒãŸæ–‡æ›¸æ•°ã‚’å¾—ã‚‹ã«ã¯ã€é–¢æ•° `oddnum' を用ã„る。

int oddnum(ODEUM *odeum);
`odeum' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«æ ¼ç´ã•ã‚ŒãŸæ–‡æ›¸ã®æ•°ã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰ -1 ã§ã‚る。

ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«æ ¼ç´ã•れãŸå˜èªžæ•°ã‚’å¾—ã‚‹ã«ã¯ã€é–¢æ•° `odwnum' を用ã„る。

int odwnum(ODEUM *odeum);
`odeum' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«æ ¼ç´ã•れãŸèªžã®æ•°ã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰ -1 ã§ã‚る。I/Oãƒãƒƒãƒ•ã‚¡ã«ã‚ˆã‚Šã€æˆ»ã‚Šå€¤ã¯å®Ÿéš›ã®ã‚µã‚¤ã‚ºã‚ˆã‚Šå°ã•ããªã‚‹å ´åˆãŒã‚る。

データベースãƒãƒ³ãƒ‰ãƒ«ãŒãƒ©ã‚¤ã‚¿ã‹ã©ã†ã‹ã‚’調ã¹ã‚‹ã«ã¯ã€é–¢æ•° `odwritable' を用ã„る。

int odwritable(ODEUM *odeum);
`odeum' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚戻り値ã¯ãƒ©ã‚¤ã‚¿ãªã‚‰çœŸã§ã‚りã€ãã†ã§ãªã‘れã°å½ã§ã‚る。

データベースã«è‡´å‘½çš„エラーãŒèµ·ããŸã‹ã©ã†ã‹ã‚’調ã¹ã‚‹ã«ã¯ã€é–¢æ•° `odfatalerror' を用ã„る。

int odfatalerror(ODEUM *odeum);
`odeum' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚戻り値ã¯è‡´å‘½çš„エラーãŒã‚れã°çœŸã§ã‚りã€ãã†ã§ãªã‘れã°å½ã§ã‚る。

データベースディレクトリã®inode番å·ã‚’å¾—ã‚‹ã«ã¯ã€é–¢æ•° `odinode' を用ã„る。

int odinode(ODEUM *odeum);
`odeum' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚戻り値ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã®inode番å·ã§ã‚る。

ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®æœ€çµ‚更新時刻を得るã«ã¯ã€é–¢æ•° `odmtime' を用ã„る。

time_t odmtime(ODEUM *odeum);
`odeum' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚戻り値ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®æœ€çµ‚更新時刻ã§ã‚る。

複数ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’マージã™ã‚‹ã«ã¯ã€é–¢æ•° `odmerge' を用ã„る。

int odmerge(const char *name, const CBLIST *elemnames);
`name' ã¯ä½œæˆã™ã‚‹ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã®åå‰ã‚’指定ã™ã‚‹ã€‚`elemnames' ã¯è¦ç´ ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®åå‰ã®ãƒªã‚¹ãƒˆã‚’指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰çœŸã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰å½ã§ã‚る。åŒã˜URLã‚’æŒã¤è¤‡æ•°ã®æ–‡æ›¸ãŒç¾ã‚ŒãŸå ´åˆã€æœ€åˆã«ç¾ã‚ŒãŸã‚‚ã®ãŒæŽ¡ç”¨ã•ã‚Œã€æ®‹ã‚Šã¯ç„¡è¦–ã•れる。

データベースディレクトリを削除ã™ã‚‹ã«ã¯ã€é–¢æ•° `odremove' を用ã„る。

int odremove(const char *name);
`name' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã®åå‰ã‚’指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰çœŸã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰å½ã§ã‚る。データベースディレクトリã®ä¸­ã«ã¯QDBMã®ä»–ã®APIã«ã‚ˆã‚‹ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’ç½®ãã“ã¨ãŒã§ãã‚‹ãŒã€ãれらもã“ã®é–¢æ•°ã«ã‚ˆã£ã¦å‰Šé™¤ã•れる。

文書ãƒãƒ³ãƒ‰ãƒ«ã‚’作æˆã™ã‚‹ã«ã¯ã€é–¢æ•° `oddocopen' を用ã„る。

ODDOC *oddocopen(const char *uri);
`uri' ã¯æ–‡æ›¸ã®URIを指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ–‡æ›¸ãƒãƒ³ãƒ‰ãƒ«ã§ã‚る。新ã—ã„æ–‡æ›¸ã®ID番å·ã¯å®šç¾©ã•れãªã„。ãれã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«æ ¼ç´ã—ãŸéš›ã«å®šç¾©ã•れる。

文書ãƒãƒ³ãƒ‰ãƒ«ã‚’破棄ã™ã‚‹ã«ã¯ã€é–¢æ•° `oddocclose' を用ã„る。

void oddocclose(ODDOC *doc);
`doc' ã¯æ–‡æ›¸ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚é–‰ã˜ãŸãƒãƒ³ãƒ‰ãƒ«ã®é ˜åŸŸã¯è§£æ”¾ã•れるã®ã§ã€ä»¥å¾Œã¯åˆ©ç”¨ã§ããªããªã‚‹ã€‚

文書ã«å±žæ€§ã‚’追加ã™ã‚‹ã«ã¯ã€é–¢æ•° `oddocaddattr' を用ã„る。

void oddocaddattr(ODDOC *doc, const char *name, const char *value);
`doc' ã¯æ–‡æ›¸ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`name' ã¯å±žæ€§åã®æ–‡å­—列を指定ã™ã‚‹ã€‚`value' ã¯å±žæ€§å€¤ã®æ–‡å­—列を指定ã™ã‚‹ã€‚

文書ã«èªžã‚’追加ã™ã‚‹ã«ã¯ã€é–¢æ•° `oddocaddword' を用ã„る。

void oddocaddword(ODDOC *doc, const char *normal, const char *asis);
`doc' ã¯æ–‡æ›¸ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`normal' ã¯èªžã®æ­£è¦å½¢ã®æ–‡å­—列を指定ã™ã‚‹ã€‚æ­£è¦å½¢ã¯è»¢ç½®ã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹ã®ã‚­ãƒ¼ã¨ã—ã¦æ‰±ã‚れる。正è¦å½¢ãŒç©ºæ–‡å­—列ã®å ´åˆã€ãã®èªžã¯è»¢ç½®ã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹ã«å映ã•れãªã„。`asis' ã¯èªžã®å‡ºç¾å½¢ã®æ–‡å­—列を指定ã™ã‚‹ã€‚出ç¾å½¢ã¯ã‚¢ãƒ—ãƒªã‚±ãƒ¼ã‚·ãƒ§ãƒ³ãŒæ–‡æ›¸ã‚’å–å¾—ã—ãŸéš›ã«åˆ©ç”¨ã•れる。

文書ã®IDã‚’å¾—ã‚‹ã«ã¯ã€é–¢æ•° `oddocid' を用ã„る。

int oddocid(const ODDOC *doc);
`doc' ã¯æ–‡æ›¸ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ–‡æ›¸ã®ID番å·ã§ã‚る。

文書ã®URIã‚’å¾—ã‚‹ã«ã¯ã€é–¢æ•° `oddocuri' を用ã„る。

const char *oddocuri(const ODDOC *doc);
`doc' ã¯æ–‡æ›¸ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ–‡æ›¸ã®URIã®æ–‡å­—列ã§ã‚る。

文書ã®å±žæ€§å€¤ã‚’å¾—ã‚‹ã«ã¯ã€é–¢æ•° `oddocgetattr' を用ã„る。

const char *oddocgetattr(const ODDOC *doc, const char *name);
`doc' ã¯æ–‡æ›¸ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`name' ã¯å±žæ€§åã®æ–‡å­—列を指定ã™ã‚‹ã€‚戻り値ã¯å±žæ€§å€¤ã®æ–‡å­—列ã§ã‚ã‚‹ã‹ã€è©²å½“ãŒãªã‘れ㰠`NULL' ã§ã‚る。

文書内ã®èªžç¾¤ã®æ­£è¦å½¢ã®ãƒªã‚¹ãƒˆã‚’å¾—ã‚‹ã«ã¯ã€é–¢æ•° `oddocnwords' を用ã„る。

const CBLIST *oddocnwords(const ODDOC *doc);
`doc' ã¯æ–‡æ›¸ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£è¦å½¢ã®èªžç¾¤ã‚’æ ¼ç´ã—ãŸãƒªã‚¹ãƒˆãƒãƒ³ãƒ‰ãƒ«ã§ã‚る。

文書内ã®èªžç¾¤ã®å‡ºç¾å½¢ã®ãƒªã‚¹ãƒˆã‚’å¾—ã‚‹ã«ã¯ã€é–¢æ•° `oddocawords' を用ã„る。

const CBLIST *oddocawords(const ODDOC *doc);
`doc' ã¯æ–‡æ›¸ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚戻り値ã¯å‡ºç¾å½¢ã®èªžç¾¤ã‚’æ ¼ç´ã—ãŸãƒªã‚¹ãƒˆãƒãƒ³ãƒ‰ãƒ«ã§ã‚る。

文書ã®ã‚­ãƒ¼ãƒ¯ãƒ¼ãƒ‰ã®æ­£è¦å½¢ã¨ãã®ã‚¹ã‚³ã‚¢ã®ãƒžãƒƒãƒ—ã‚’å¾—ã‚‹ã«ã¯ã€é–¢æ•° `oddocscores' を用ã„る。

CBMAP *oddocscores(const ODDOC *doc, int max, ODEUM *odeum);
`doc' ã¯æ–‡æ›¸ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`max' ã¯å–å¾—ã™ã‚‹ã‚­ãƒ¼ãƒ¯ãƒ¼ãƒ‰ã®æœ€å¤§æ•°ã‚’指定ã™ã‚‹ã€‚`odeum' ㌠`NULL' ã§ãªã‘れã°ã€ãれを用ã„ã¦é‡ã¿ã¥ã‘ã®ãŸã‚ã®IDFãŒç®—出ã•れる。戻り値ã¯ã‚­ãƒ¼ãƒ¯ãƒ¼ãƒ‰ã¨ãã®ã‚¹ã‚³ã‚¢ã‚’æ ¼ç´ã—ãŸãƒžãƒƒãƒ—ãƒãƒ³ãƒ‰ãƒ«ã§ã‚る。スコアã¯10é€²æ•°ã®æ–‡å­—列ã§è¡¨ç¾ã•れる。戻り値ã®ãƒãƒ³ãƒ‰ãƒ«ã¯é–¢æ•° `cbmapopen' ã§é–‹ã‹ã‚Œã‚‹ã®ã§ã€ä¸è¦ã«ãªã£ãŸã‚‰ `cbmapclose' ã§é–‰ã˜ã‚‹ã¹ãã§ã‚る。

テキストを分解ã—ã¦èªžç¾¤ã®å‡ºç¾å½¢ã®ãƒªã‚¹ãƒˆã‚’å¾—ã‚‹ã«ã¯ã€é–¢æ•° `odbreaktext' を用ã„る。

CBLIST *odbreaktext(const char *text);
`text' ã¯ãƒ†ã‚­ã‚¹ãƒˆã®æ–‡å­—列を指定ã™ã‚‹ã€‚戻り値ã¯èªžç¾¤ã®å‡ºç¾å½¢ã®ãƒªã‚¹ãƒˆãƒãƒ³ãƒ‰ãƒ«ã§ã‚る。語群ã¯ç©ºç™½æ–‡å­—ã¨ãƒ”リオドやコンマ等ã®åŒºåˆ‡ã‚Šæ–‡å­—ã§åˆ†å‰²ã•れる。戻り値ã®ãƒãƒ³ãƒ‰ãƒ«ã¯é–¢æ•° `cblistopen' ã§é–‹ã‹ã‚Œã‚‹ã®ã§ã€ä¸è¦ã«ãªã£ãŸã‚‰ `cblistclose' ã§é–‰ã˜ã‚‹ã¹ãã§ã‚る。

èªžã®æ­£è¦å½¢ã‚’å–å¾—ã™ã‚‹ã«ã¯ã€é–¢æ•° `odnormalizeword' を用ã„る。

char *odnormalizeword(const char *asis);
`asis' ã¯èªžã®å‡ºç¾å½¢ã®æ–‡å­—列を指定ã™ã‚‹ã€‚戻り値ã¯èªžã®æ­£è¦å½¢ã®æ–‡å­—列ã§ã‚る。ASCIIコードã®ã‚¢ãƒ«ãƒ•ァベットã¯å°æ–‡å­—ã«çµ±ä¸€ã•れる。区切り文字ã®ã¿ã‹ã‚‰ãªã‚‹æ–‡å­—ã¯ç©ºæ–‡å­—列ã¨ã—ã¦æ‰±ã‚れる。戻り値ã®é ˜åŸŸã¯ `malloc' ã§ç¢ºä¿ã•れるã®ã§ã€ä¸è¦ã«ãªã£ãŸã‚‰ `free' ã§è§£æ”¾ã™ã‚‹ã¹ãã§ã‚る。

二ã¤ã®æ–‡æ›¸é›†åˆã‹ã‚‰ãã®å…±é€šé›†åˆã‚’å¾—ã‚‹ã«ã¯ã€é–¢æ•° `odpairsand' を用ã„る。

ODPAIR *odpairsand(ODPAIR *apairs, int anum, ODPAIR *bpairs, int bnum, int *np);
`apairs' ã¯å‰è€…ã®æ–‡æ›¸é›†åˆã®é…列を指定ã™ã‚‹ã€‚`anum' ã¯å‰è€…ã®é…列ã®è¦ç´ æ•°ã‚’指定ã™ã‚‹ã€‚`apairs' ã¯å¾Œè€…ã®æ–‡æ›¸é›†åˆã®é…列を指定ã™ã‚‹ã€‚`anum' ã¯å¾Œè€…ã®é…列ã®è¦ç´ æ•°ã‚’指定ã™ã‚‹ã€‚`np' ã®å‚ç…§å…ˆã«ã¯ã€æˆ»ã‚Šå€¤ã®é…列ã®è¦ç´ æ•°ãŒæ ¼ç´ã•ã‚Œã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ–°ã—ã„æ–‡æ›¸é›†åˆã®é…列ã¸ã®ãƒã‚¤ãƒ³ã‚¿ã§ã‚りã€å„è¦ç´ ã¯äºŒã¤ã®é›†åˆã«å…±é€šã—ã¦å±žã™ã‚‹ã‚‚ã®ã§ã‚る。å„è¦ç´ ã¯ã‚¹ã‚³ã‚¢ã®é™é †ã§ä¸¦ã¹ã‚‰ã‚Œã‚‹ã€‚戻り値ã®é ˜åŸŸã¯ `malloc' ã§ç¢ºä¿ã•れるã®ã§ã€ä¸è¦ã«ãªã£ãŸã‚‰ `free' ã§è§£æ”¾ã™ã‚‹ã¹ãã§ã‚る。

二ã¤ã®æ–‡æ›¸é›†åˆã‹ã‚‰ãã®å’Œé›†åˆã‚’å¾—ã‚‹ã«ã¯ã€é–¢æ•° `odpairsor' を用ã„る。

ODPAIR *odpairsor(ODPAIR *apairs, int anum, ODPAIR *bpairs, int bnum, int *np);
`apairs' ã¯å‰è€…ã®æ–‡æ›¸é›†åˆã®é…列を指定ã™ã‚‹ã€‚`anum' ã¯å‰è€…ã®é…列ã®è¦ç´ æ•°ã‚’指定ã™ã‚‹ã€‚`apairs' ã¯å¾Œè€…ã®æ–‡æ›¸é›†åˆã®é…列を指定ã™ã‚‹ã€‚`anum' ã¯å¾Œè€…ã®é…列ã®è¦ç´ æ•°ã‚’指定ã™ã‚‹ã€‚`np' ã®å‚ç…§å…ˆã«ã¯ã€æˆ»ã‚Šå€¤ã®é…列ã®è¦ç´ æ•°ãŒæ ¼ç´ã•ã‚Œã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ–°ã—ã„æ–‡æ›¸é›†åˆã®é…列ã¸ã®ãƒã‚¤ãƒ³ã‚¿ã§ã‚りã€å„è¦ç´ ã¯äºŒã¤ã®é›†åˆã®ä¸¡æ–¹ã‚ã‚‹ã„ã¯ã©ã¡ã‚‰ã‹ä¸€æ–¹ã«å±žã™ã‚‹ã‚‚ã®ã§ã‚る。å„è¦ç´ ã¯ã‚¹ã‚³ã‚¢ã®é™é †ã§ä¸¦ã¹ã‚‰ã‚Œã‚‹ã€‚戻り値ã®é ˜åŸŸã¯ `malloc' ã§ç¢ºä¿ã•れるã®ã§ã€ä¸è¦ã«ãªã£ãŸã‚‰ `free' ã§è§£æ”¾ã™ã‚‹ã¹ãã§ã‚る。

二ã¤ã®æ–‡æ›¸é›†åˆã‹ã‚‰ãã®å·®é›†åˆã‚’å¾—ã‚‹ã«ã¯ã€é–¢æ•° `odpairsnotand' を用ã„る。

ODPAIR *odpairsnotand(ODPAIR *apairs, int anum, ODPAIR *bpairs, int bnum, int *np);
`apairs' ã¯å‰è€…ã®æ–‡æ›¸é›†åˆã®é…列を指定ã™ã‚‹ã€‚`anum' ã¯å‰è€…ã®é…列ã®è¦ç´ æ•°ã‚’指定ã™ã‚‹ã€‚`apairs' ã¯å¾Œè€…ã®æ–‡æ›¸é›†åˆã®é…列を指定ã™ã‚‹ã€‚`anum' ã¯å¾Œè€…ã®é…列ã®è¦ç´ æ•°ã‚’指定ã™ã‚‹ã€‚`np' ã®å‚ç…§å…ˆã«ã¯ã€æˆ»ã‚Šå€¤ã®é…列ã®è¦ç´ æ•°ãŒæ ¼ç´ã•ã‚Œã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ–°ã—ã„æ–‡æ›¸é›†åˆã®é…列ã¸ã®ãƒã‚¤ãƒ³ã‚¿ã§ã‚りã€å„è¦ç´ ã¯å‰è€…ã®é›†åˆã«ã¯å±žã™ã‚‹ãŒå¾Œè€…ã®é›†åˆã«ã¯å±žã•ãªã„ã‚‚ã®ã§ã‚る。å„è¦ç´ ã¯ã‚¹ã‚³ã‚¢ã®é™é †ã§ä¸¦ã¹ã‚‰ã‚Œã‚‹ã€‚戻り値ã®é ˜åŸŸã¯ `malloc' ã§ç¢ºä¿ã•れるã®ã§ã€ä¸è¦ã«ãªã£ãŸã‚‰ `free' ã§è§£æ”¾ã™ã‚‹ã¹ãã§ã‚る。

文書集åˆã‚’スコアã®é™é †ã§ä¸¦ã¹ã‚‹ã«ã¯ã€é–¢æ•° `odpairssort' を用ã„る。

void odpairssort(ODPAIR *pairs, int pnum);
`pairs' ã¯æ–‡æ›¸é›†åˆã®é…列を指定ã™ã‚‹ã€‚`pnum' ã¯ãã®é…列ã®è¦ç´ æ•°ã‚’指定ã™ã‚‹ã€‚

ã‚ã‚‹æ•°ã®è‡ªç„¶å¯¾æ•°ã‚’å¾—ã‚‹ã«ã¯ã€é–¢æ•° `odlogarithm' を用ã„る。

double odlogarithm(double x);
`x' ã¯ã‚る数を指定ã™ã‚‹ã€‚戻り値ã¯ãã®æ•°ã®è‡ªç„¶å¯¾æ•°ã§ã‚る。もã—ãã®æ•°ãŒ 1.0 以下ã§ã‚れã°ã€æˆ»ã‚Šå€¤ã¯ 0.0 ã¨ãªã‚‹ã€‚ã“ã®é–¢æ•°ã¯ã‚¢ãƒ—ãƒªã‚±ãƒ¼ã‚·ãƒ§ãƒ³ãŒæ¤œç´¢çµæžœã®IDFを算出ã™ã‚‹éš›ã«ä¾¿åˆ©ã§ã‚る。

二ã¤ã®ãƒ™ã‚¯ãƒˆãƒ«ã®ãªã™è§’ã®ä½™å¼¦ã‚’å¾—ã‚‹ã«ã¯ã€é–¢æ•° `odvectorcosine' を用ã„る。

double odvectorcosine(const int *avec, const int *bvec, int vnum);
`avec' ã¯å‰è€…ã®æ•°å€¤é…列を指定ã™ã‚‹ã€‚`bvec' ã¯å¾Œè€…ã®æ•°å€¤é…列を指定ã™ã‚‹ã€‚`vnum' ã¯å„々ã®é…列ã®è¦ç´ æ•°ã‚’指定ã™ã‚‹ã€‚戻り値ã¯äºŒã¤ã®ãƒ™ã‚¯ãƒˆãƒ«ã®ãªã™è§’ã®ä½™å¼¦ã§ã‚る。ã“ã®é–¢æ•°ã¯ã‚¢ãƒ—ãƒªã‚±ãƒ¼ã‚·ãƒ§ãƒ³ãŒæ–‡æ›¸ã®é¡žä¼¼åº¦ã‚’算出ã™ã‚‹éš›ã«ä¾¿åˆ©ã§ã‚る。

性能を調整ã™ã‚‹å¤§åŸŸçš„ãªãƒ‘ラメータを指定ã™ã‚‹ã«ã¯ã€é–¢æ•° `odsettuning' を用ã„る。

void odsettuning(int ibnum, int idnum, int cbnum, int csiz);
`ibnum' ã¯è»¢ç½®ã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹ã®ãƒã‚±ãƒƒãƒˆæ•°ã‚’指定ã™ã‚‹ã€‚`idnum' ã¯è»¢ç½®ã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹ã®åˆ†å‰²æ•°ã‚’指定ã™ã‚‹ã€‚`cbnum' ã¯ãƒ€ãƒ¼ãƒ†ã‚£ãƒãƒƒãƒ•ã‚¡ã®ãƒã‚±ãƒƒãƒˆæ•°ã‚’指定ã™ã‚‹ã€‚`csiz' ã¯ãƒ€ãƒ¼ãƒ†ã‚£ãƒãƒƒãƒ•ã‚¡ã«ä½¿ã†ãƒ¡ãƒ¢ãƒªã®æœ€å¤§ãƒã‚¤ãƒˆæ•°ã‚’指定ã™ã‚‹ã€‚デフォルトã®è¨­å®šã¯ `odsettuning(32749, 7, 262139, 8388608)' ã«ç›¸å½“ã™ã‚‹ã€‚ã“ã®é–¢æ•°ã¯ãƒãƒ³ãƒ‰ãƒ«ã‚’é–‹ãå‰ã«å‘¼ã³å‡ºã™ã¹ãã§ã‚る。

テキストを分解ã—ã¦å‡ºç¾å½¢ã¨æ­£è¦å½¢ã‚’別々ã®ãƒªã‚¹ãƒˆã«æ ¼ç´ã™ã‚‹ã«ã¯ã€é–¢æ•° `odanalyzetext' を用ã„る。

void odanalyzetext(ODEUM *odeum, const char *text, CBLIST *awords, CBLIST *nwords);
`odeum' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`text' ã¯ãƒ†ã‚­ã‚¹ãƒˆã®æ–‡å­—列を指定ã™ã‚‹ã€‚`awords' ã¯å‡ºç¾åž‹ã‚’æ ¼ç´ã™ã‚‹ãƒªã‚¹ãƒˆãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`nwords' ã¯æ­£è¦åž‹ã‚’æ ¼ç´ã™ã‚‹ãƒªã‚¹ãƒˆãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ãŒã€`NULL' ãªã‚‰ç„¡è¦–ã•れる。語群ã¯ç©ºç™½æ–‡å­—ã¨ãƒ”リオドやコンマ等ã®åŒºåˆ‡ã‚Šæ–‡å­—ã§åˆ†å‰²ã•れる。

関数 `odanalyzetext' ã§ä½¿ã‚れる文字ã®åˆ†é¡žã‚’設定ã™ã‚‹ã«ã¯ã€é–¢æ•° `odsetcharclass' を用ã„る。

void odsetcharclass(ODEUM *odeum, const char *spacechars, const char *delimchars, const char *gluechars);
`odeum' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`spachechars' ã¯ç©ºç™½æ–‡å­—ã‚’å«ã‚€æ–‡å­—列を指定ã™ã‚‹ã€‚`delimchars' ã¯åŒºåˆ‡ã‚Šæ–‡å­—ã‚’å«ã‚€æ–‡å­—列を指定ã™ã‚‹ã€‚`gluechars' ã¯æŽ¥ç€æ–‡å­—ã‚’å«ã‚€æ–‡å­—列を指定ã™ã‚‹ã€‚

å°ã•ãªå•ã„åˆã‚ã›è¨€èªžã‚’使ã£ã¦æ¤œç´¢ã‚’行ã†ã«ã¯ã€é–¢æ•° `odquery' を用ã„る。

ODPAIR *odquery(ODEUM *odeum, const char *query, int *np, CBLIST *errors);
`odeum' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚`query' ã¯å•ã„åˆã‚ã›è¨€èªžã®æ–‡å­—列を指定ã™ã‚‹ã€‚`np' ã®å‚ç…§å…ˆã«ã¯ã€æˆ»ã‚Šå€¤ã®é…列ã®è¦ç´ æ•°ãŒæ ¼ç´ã•れる。`error' ã¯ã‚¨ãƒ©ãƒ¼ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚’æ ¼ç´ã™ã‚‹ãƒªã‚¹ãƒˆãƒãƒ³ãƒ‰ãƒ«ã‚’指定ã™ã‚‹ã€‚æˆ»ã‚Šå€¤ã¯æ­£å¸¸ãªã‚‰é…列ã¸ã®ãƒã‚¤ãƒ³ã‚¿ã§ã‚りã€ã‚¨ãƒ©ãƒ¼ãªã‚‰ `NULL' ã§ã‚る。ãã®é…列ã®å„è¦ç´ ã¯æ–‡æ›¸ã®ID番å·ã¨ã‚¹ã‚³ã‚¢ã®ãƒšã‚¢ã§ã‚りã€ã‚¹ã‚³ã‚¢ã®é™é †ã§ä¸¦ã¹ã‚‰ã‚Œã‚‹ã€‚検索語ã«è©²å½“ã™ã‚‹æ–‡æ›¸ãŒä¸€ã¤ã‚‚ãªã‹ã£ãŸã¨ã—ã¦ã‚‚エラーã«ã¯ãªã‚‰ãšã«ã€ç©ºã®é…列を返ã™ã€‚戻り値ã®é ˜åŸŸã¯ `malloc' ã§ç¢ºä¿ã•れるã®ã§ã€ä¸è¦ã«ãªã£ãŸã‚‰ `free' ã§è§£æ”¾ã™ã‚‹ã¹ãã§ã‚る。é…列ã®å„è¦ç´ ã«ã¯æ—¢ã«å‰Šé™¤ã•ã‚ŒãŸæ–‡æ›¸ã®ãƒ‡ãƒ¼ã‚¿ã‚‚å«ã¾ã‚Œã‚‹ã“ã¨ã«æ³¨æ„ã™ã¹ãã§ã‚る。

サンプルコード

æ–‡æ›¸ã‚’ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«æ ¼ç´ã™ã‚‹ã‚µãƒ³ãƒ—ルコードを以下ã«ç¤ºã™ã€‚

#include <depot.h>
#include <cabin.h>
#include <odeum.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#define DBNAME   "index"

int main(int argc, char **argv){
  ODEUM *odeum;
  ODDOC *doc;
  CBLIST *awords;
  const char *asis;
  char *normal;
  int i;

  /* データベースを開ã */
  if(!(odeum = odopen(DBNAME, OD_OWRITER | OD_OCREAT))){
    fprintf(stderr, "odopen: %s\n", dperrmsg(dpecode));
    return 1;
  }

  /* 文書ãƒãƒ³ãƒ‰ãƒ«ã‚’å–å¾—ã™ã‚‹ */
  doc = oddocopen("http://www.foo.bar/baz.txt");

  /* 文書ã®å±žæ€§ã‚’設定ã™ã‚‹ */
  oddocaddattr(doc, "title", "Balcony Scene");
  oddocaddattr(doc, "author", "Shakespeare");

  /* テキストを分解ã—ã¦èªžã®ãƒªã‚¹ãƒˆã‚’å¾—ã‚‹ */
  awords = odbreaktext("Parting is such sweet sorrow.");

  /* å„語を文書ãƒãƒ³ãƒ‰ãƒ«ã«è¨­å®šã™ã‚‹ */
  for(i = 0; i < cblistnum(awords); i++){
    /* 語ã®ãƒªã‚¹ãƒˆã‹ã‚‰ä¸€èªžã‚’å–り出㙠*/
    asis = cblistval(awords, i, NULL);
    /* 出ç¾å½¢ã‹ã‚‰æ­£è¦å½¢ã‚’生æˆã™ã‚‹ */
    normal = odnormalizeword(asis);
    /* 語を文書ãƒãƒ³ãƒ‰ãƒ«ã«è¨­å®šã™ã‚‹ */
    oddocaddword(doc, normal, asis);
    /* æ­£è¦å½¢ã®é ˜åŸŸã‚’解放ã™ã‚‹ */
    free(normal);
  }

  /* 文書をデータベースã«ç™»éŒ²ã™ã‚‹ */
  if(!odput(odeum, doc, -1, 1)){
    fprintf(stderr, "odput: %s\n", dperrmsg(dpecode));
  }

  /* 語ã®ãƒªã‚¹ãƒˆã‚’解放ã™ã‚‹ */
  cblistclose(awords);

  /* 文書ãƒãƒ³ãƒ‰ãƒ«ã‚’解放ã™ã‚‹ */
  oddocclose(doc);

  /* データベースを閉ã˜ã‚‹ */
  if(!odclose(odeum)){
    fprintf(stderr, "odclose: %s\n", dperrmsg(dpecode));
    return 1;
  }

  return 0;
}

ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹å†…ã®æ–‡æ›¸ã‚’検索ã™ã‚‹ã‚µãƒ³ãƒ—ルコードを以下ã«ç¤ºã™ã€‚

#include <depot.h>
#include <cabin.h>
#include <odeum.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#define DBNAME   "index"

int main(int argc, char **argv){
  ODEUM *odeum;
  ODPAIR *pairs;
  ODDOC *doc;
  const CBLIST *words;
  const char *title, *author, *asis;
  int i, j, pnum;

  /* データベースをå–å¾—ã™ã‚‹ */
  if(!(odeum = odopen(DBNAME, OD_OREADER))){
    fprintf(stderr, "odopen: %s\n", dperrmsg(dpecode));
    return 1;
  }

  /* æ–‡æ›¸ã®æ¤œç´¢ã‚’行ㆠ*/
  if((pairs = odsearch(odeum, "sorrow", -1, &pnum)) != NULL){

    /* 文書ã®é…列を走査ã™ã‚‹ */
    for(i = 0; i < pnum; i++){
      /* 文書ãƒãƒ³ãƒ‰ãƒ«ã‚’å–å¾—ã™ã‚‹ */
      if(!(doc = odgetbyid(odeum, pairs[i].id))) continue;
      /* 文書ã®å±žæ€§ã‚’表示ã™ã‚‹ */
      printf("URI: %s\n", oddocuri(doc));
      title = oddocgetattr(doc, "title");
      if(title) printf("TITLE: %s\n", title);
      author = oddocgetattr(doc, "author");
      if(author) printf("AUTHOR: %s\n", author);
      /* 文書内ã®èªžã‚’出ç¾å½¢ã§è¡¨ç¤ºã™ã‚‹ */
      printf("WORDS:");
      words = oddocawords(doc);
      for(j = 0; j < cblistnum(words); j++){
        asis = cblistval(words, j, NULL);
        printf(" %s", asis);
      }
      putchar('\n');
      /* 文書ãƒãƒ³ãƒ‰ãƒ«ã‚’解放ã™ã‚‹ */
      oddocclose(doc);
    }

    /* 文書ã®é…列を解放ã™ã‚‹ */
    free(pairs);

  } else {
    fprintf(stderr, "odsearch: %s\n", dperrmsg(dpecode));
  }

  /* データベースを閉ã˜ã‚‹ */
  if(!odclose(odeum)){
    fprintf(stderr, "odclose: %s\n", dperrmsg(dpecode));
    return 1;
  }

  return 0;
}

注記

Odeumを利用ã—ãŸãƒ—ログラムをビルドã™ã‚‹æ–¹æ³•ã¯ã€Depotã®å ´åˆã¨å…¨ãåŒã˜ã§ã‚る。

gcc -I/usr/local/include -o sample sample.c -L/usr/local/lib -lqdbm

POSIXスレッドを有効ã«ã—ã¦QDBMをビルドã—ãŸå ´åˆã€å¤–部変数 `dpecode' ã¯ã‚¹ãƒ¬ãƒƒãƒ‰å›ºæœ‰ãƒ‡ãƒ¼ã‚¿ã¸ã®å‚ç…§ã¨ã—ã¦æ‰±ã‚れã€Odeumã®å„関数ã¯ãƒªã‚¨ãƒ³ãƒˆãƒ©ãƒ³ãƒˆã«ãªã‚‹ã€‚ãã®å ´åˆã€ã‚¹ãƒ¬ãƒƒãƒ‰é–“ã§åŒæ™‚ã«åŒã˜ãƒãƒ³ãƒ‰ãƒ«ã«ã‚¢ã‚¯ã‚»ã‚¹ã—ãªã„é™ã‚Šã¯ã€å„関数ã¯ã‚¹ãƒ¬ãƒƒãƒ‰ã‚»ãƒ¼ãƒ•ã§ã‚る。ãŸã ã—ã€`errno' ã‚„ `malloc' ç­‰ãŒã‚¹ãƒ¬ãƒƒãƒ‰ã‚»ãƒ¼ãƒ•ãªå‡¦ç†ç³»ã§ã‚ã‚‹ã“ã¨ãŒå‰æã¨ãªã‚‹ã€‚

ZLIBを有効ã«ã—ã¦QDBMをビルドã—ãŸå ´åˆã€æ–‡æ›¸å±žæ€§ç”¨ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹å†…ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã¯åœ§ç¸®ã•れã¦ä¿å­˜ã•れる。ãã®å ´åˆã€ã‚µã‚¤ã‚ºãŒ30%以下ã«ãªã‚‹ã€‚ã—ãŸãŒã£ã¦ã€Odeumを利用ã™ã‚‹å ´åˆã¯ZLIBを有効ã«ã—ãŸæ–¹ãŒã‚ˆã„。ZLIBを有効ã«ã—ã¦ä½œæˆã—ãŸOdeumã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’ã€ZLIBを有効ã«ã—ã¦ã„ãªã„環境ã§åˆ©ç”¨ã™ã‚‹ã“ã¨ã¯ã§ããšã€ã¾ãŸãã®é€†ã‚‚åŒæ§˜ã§ã‚る。ZLIBãŒæœ‰åйã§ãªãLZOãŒæœ‰åйãªå ´åˆã¯ã€ZLIBã®å¤‰ã‚りã«LZOãŒç”¨ã„られる。

å•ã„åˆã‚ã›è¨€èªž

関数 `odquery' ã®å•ã„åˆã‚ã›è¨€èªžã¯ä»¥ä¸‹ã®æ–‡æ³•ã«åŸºã¥ã。

expr ::= subexpr ( op subexpr )*
subexpr ::= WORD
subexpr ::= LPAREN expr RPAREN

演算å­ã¨ã—ã¦ã¯ "&"(AND)㨠"|"(OR)㨠"!"(NOTAND)ãŒåˆ©ç”¨ã§ãる。ã¾ãŸã€æ‹¬å¼§ "()" を使ã†ã“ã¨ã§æ¼”ç®—å­ã®è©•価順åºã‚’制御ã™ã‚‹ã“ã¨ãŒã§ãる。å•ã„åˆã‚ã›ã®æ–‡å­—列ã¯é–¢æ•° `odanalyzetext' を用ã„ã¦åˆ†è§£ã•れるã®ã§ã€"&"ã€"|"ã€"!"ã€"("ã€")" ã¯åŒºåˆ‡ã‚Šæ–‡å­—ã¨ã—ã¦è¨­å®šã•れã¦ã„ã‚‹å¿…è¦ãŒã‚る。ã¾ãŸã€ç©ºç™½ã§å˜èªžã‚’区切ã£ã¦ã‚‚ "&" ã§åŒºåˆ‡ã£ãŸã®ã¨åŒã˜ã“ã¨ã«ãªã‚‹ã€‚ã¤ã¾ã‚Š "joe blow" 㯠"joe & blow" ã¨åŒã˜ã§ã‚る。

å•ã„åˆã‚ã›æ–‡å­—åˆ—ã®æ–‡å­—コードã¯å¯¾è±¡æ–‡æ›¸ã®æ–‡å­—コードã¨ä¸€è‡´ã—ã¦ã„ã‚‹å¿…è¦ãŒã‚る。ã¾ãŸã€ç©ºç™½æ–‡å­—ã¨åŒºåˆ‡ã‚Šæ–‡å­—ã¨æŽ¥ç€æ–‡å­—ã«æŒ‡å®šã§ãã‚‹ã®ã¯1ãƒã‚¤ãƒˆæ–‡å­—ã ã‘ã§ã‚る。


Odeum用コマンド

Odeumã«å¯¾å¿œã™ã‚‹ã‚³ãƒžãƒ³ãƒ‰ãƒ©ã‚¤ãƒ³ã‚¤ãƒ³ã‚¿ãƒ•ェースã¯ä»¥ä¸‹ã®ã‚‚ã®ã§ã‚る。

コマンド `odmgr' ã¯Odeumã‚„ãã®ã‚¢ãƒ—リケーションã®ãƒ‡ãƒãƒƒã‚°ã«å½¹ç«‹ã¤ãƒ„ールã§ã‚る。データベースを更新ã—ãŸã‚Šã€ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®çŠ¶æ…‹ã‚’èª¿ã¹ãŸã‚Šã™ã‚‹æ©Ÿèƒ½ã‚’æŒã¤ã€‚シェルスクリプトã§å…¨æ–‡æ¤œç´¢ã‚·ã‚¹ãƒ†ãƒ ã‚’作るã®ã«ã‚‚利用ã§ãã‚‹ã€‚ä»¥ä¸‹ã®æ›¸å¼ã§ç”¨ã„る。`name' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹åã€`file' ã¯ãƒ•ァイルåã€`expr' ã¯æ–‡æ›¸ã®URIã‹ID番å·ã€`words' ã¯æ¤œç´¢èªžã€`elems' ã¯è¦ç´ ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’指定ã™ã‚‹ã€‚

odmgr create name
データベースファイルを作æˆã™ã‚‹ã€‚
odmgr put [-uri str] [-title str] [-author str] [-date str] [-wmax num] [-keep] name [file]
ファイルを読ã¿è¾¼ã‚“ã§æ–‡æ›¸ã‚’追加ã™ã‚‹ã€‚`file' ã‚’çœç•¥ã™ã‚‹ã¨æ¨™æº–入力を読ã¿è¾¼ã‚€ãŒã€ãã®å ´åˆã¯URIã®æŒ‡å®šãŒå¿…é ˆã¨ãªã‚‹ã€‚
odmgr out [-id] name expr
URIã«å¯¾å¿œã™ã‚‹æ–‡æ›¸ã‚’削除ã™ã‚‹ã€‚
odmgr get [-id] [-t|-h] name expr
URIã«å¯¾å¿œã™ã‚‹æ–‡æ›¸ã‚’表示ã™ã‚‹ã€‚å‡ºåŠ›ã¯æ–‡æ›¸ã®ID番å·ã¨URIã¨ã‚¹ã‚³ã‚¢ã‚’タブã§åŒºåˆ‡ã£ãŸã‚‚ã®ã§ã‚る。
odmgr search [-max num] [-or] [-idf] [-t|-h|-n] name words...
指定ã—ãŸèªžã‚’å«ã‚€æ–‡æ›¸ã‚’検索ã™ã‚‹ã€‚出力ã®ç¬¬1行ã¯ã€æ¤œç´¢èªžå…¨ä½“ã®è©²å½“æ•°ã¨å„検索語ãŠã‚ˆã³ãã®è©²å½“数をタブã§åŒºåˆ‡ã£ãŸã‚‚ã®ã§ã‚る。第2行以é™ã¯ã€è©²å½“ã®å„文書ã®ID番å·ã¨URIã¨ã‚¹ã‚³ã‚¢ã‚’タブã§åŒºåˆ‡ã£ãŸã‚‚ã®ã§ã‚る。
odmgr list [-t|-h] name
データベース内ã®å…¨ã¦ã®æ–‡æ›¸ã‚’表示ã™ã‚‹ã€‚出力ã®å„è¡Œã¯æ–‡æ›¸ã®ID番å·ã¨URIã¨ã‚¹ã‚³ã‚¢ã‚’タブã§åŒºåˆ‡ã£ãŸã‚‚ã®ã§ã‚る。
odmgr optimize name
データベースを最é©åŒ–ã™ã‚‹ã€‚
odmgr inform name
データベースã®é›‘å¤šãªæƒ…報を出力ã™ã‚‹ã€‚
odmgr merge name elems...
複数ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’マージã™ã‚‹ã€‚
odmgr remove name
データベースディレクトリを削除ã™ã‚‹ã€‚
odmgr break [-h|-k|-s] [file]
ファイルを読ã¿è¾¼ã‚“ã§ã€ãƒ†ã‚­ã‚¹ãƒˆã‚’語ã«åˆ†è§£ã—ã¦å‡ºåŠ›ã™ã‚‹ã€‚出力ã®å„行ã¯å„èªžã®æ­£è¦å½¢ã¨å‡ºç¾å½¢ã‚’タブã§åŒºåˆ‡ã£ãŸã‚‚ã®ã§ã‚る。
odmgr version
QDBMã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³æƒ…報を出力ã™ã‚‹ã€‚

å„オプションã¯ä»¥ä¸‹ã®æ©Ÿèƒ½ã‚’æŒã¤ã€‚

  • -uri str : 文書ã®URIã‚’æ˜Žç¤ºçš„ã«æŒ‡å®šã™ã‚‹ã€‚
  • -title str : 文書ã®ã‚¿ã‚¤ãƒˆãƒ«ã‚’指定ã™ã‚‹ã€‚
  • -author str : 文書ã®è‘—者åを指定ã™ã‚‹ã€‚
  • -date str : æ–‡æ›¸ã®æ›´æ–°æ—¥æ™‚を指定ã™ã‚‹ã€‚
  • -wmax num : æ ¼ç´ã™ã‚‹èªžã®æœ€å¤§æ•°ã‚’指定ã™ã‚‹ã€‚
  • -keep : åŒã˜URIã®æ–‡æ›¸ãŒæ—¢å­˜ã§ã‚れã°ä¸Šæ›¸ãを行ã‚ãªã„。
  • -id : URIã§ãªãID番å·ã§æ–‡æ›¸ã‚’指定ã™ã‚‹ã€‚
  • -t : 文書ã®è©³ç´°æƒ…報をタブ区切りã§å‡ºåŠ›ã™ã‚‹ã€‚
  • -h : 文書ã®è©³ç´°æƒ…報を人間ãŒèª­ã¿ã‚„ã™ã„å½¢å¼ã§å‡ºåŠ›ã™ã‚‹ã€‚
  • -k : 文書ã®ã‚­ãƒ¼ãƒ¯ãƒ¼ãƒ‰ã®ã¿ã‚’出力ã™ã‚‹ã€‚
  • -s : 文書ã®è¦ç´„ã®ã¿ã‚’出力ã™ã‚‹ã€‚
  • -max num : 出力ã™ã‚‹æ–‡æ›¸ã®æœ€å¤§æ•°ã‚’指定ã™ã‚‹ã€‚
  • -or : AND検索ã§ãªãOR検索を行ã†ã€‚
  • -idf : IDFã§ã‚¹ã‚³ã‚¢ã‚’é‡ã¿ã¥ã‘ã™ã‚‹ã€‚
  • -n : 文書ã®IDã¨ã‚¹ã‚³ã‚¢ã®ã¿ã‚’表示ã™ã‚‹ã€‚

ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯å‡¦ç†ãŒæ­£å¸¸ã«çµ‚了ã™ã‚Œã° 0 ã‚’è¿”ã—ã€ã‚¨ãƒ©ãƒ¼ãŒã‚れã°ãれ以外ã®å€¤ã‚’è¿”ã—ã¦çµ‚了ã™ã‚‹ã€‚環境変数 `QDBMDBGFD' ã®å€¤ã¨ã—ã¦ã€å¤‰æ•° `dpecode' ã®å¤‰æ›´å±¥æ­´ã‚’出力ã™ã‚‹ãƒ•ァイルディスクリプタを指定ã“ã¨ãŒã§ãる。

コマンド `odtest' ã¯Odeumã®æ©Ÿèƒ½ãƒ†ã‚¹ãƒˆã‚„性能テストã«ç”¨ã„るツールã§ã‚る。ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã«ã‚ˆã£ã¦ç”Ÿæˆã•れãŸãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã‚’ `odmgr' ã«ã‚ˆã£ã¦è§£æžã—ãŸã‚Šã€`time' コマンドã«ã‚ˆã£ã¦ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã®å®Ÿè¡Œæ™‚間を計ã£ãŸã‚Šã™ã‚‹ã¨ã‚ˆã„ã€‚ä»¥ä¸‹ã®æ›¸å¼ã§ç”¨ã„る。`name' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹åã€`dnum' ã¯æ–‡æ›¸æ•°ã€`wnum' ã¯æ–‡æ›¸æ¯Žã®èªžæ•°ã€`pnum' ã¯èªžã®ãƒ‘ターン数を指定ã™ã‚‹ã€‚

odtest write [-tune ibnum idnum cbnum csiz] name dnum wnum pnum
無作為ãªå±žæ€§ã¨èªžã‚’æŒã¤æ–‡æ›¸ã‚’連続ã—ã¦ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«è¿½åŠ ã™ã‚‹ã€‚
odtest read name
上記ã§ç”Ÿæˆã—ãŸãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®å…¨æ–‡æ›¸ã‚’検索ã™ã‚‹ã€‚
odtest combo name
å„種æ“作ã®çµ„ã¿åˆã‚ã›ãƒ†ã‚¹ãƒˆã‚’行ã†ã€‚
odtest wicked name dnum
å„種更新æ“作を無作為ã«é¸æŠžã—ã¦å®Ÿè¡Œã™ã‚‹ã€‚

å„オプションã¯ä»¥ä¸‹ã®æ©Ÿèƒ½ã‚’æŒã¤ã€‚

  • -tune ibnum idnum cbnum csiz : 性能パラメータを指定ã™ã‚‹ã€‚

ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯å‡¦ç†ãŒæ­£å¸¸ã«çµ‚了ã™ã‚Œã° 0 ã‚’è¿”ã—ã€ã‚¨ãƒ©ãƒ¼ãŒã‚れã°ãれ以外ã®å€¤ã‚’è¿”ã—ã¦çµ‚了ã™ã‚‹ã€‚環境変数 `QDBMDBGFD' ã®å€¤ã¨ã—ã¦ã€å¤‰æ•° `dpecode' ã®å¤‰æ›´å±¥æ­´ã‚’出力ã™ã‚‹ãƒ•ァイルディスクリプタを指定ã“ã¨ãŒã§ãる。

コマンド `odidx' ã¯ãƒ­ãƒ¼ã‚«ãƒ«ãƒ•ァイルシステム上ã®ãƒ•ァイルを読ã¿è¾¼ã‚“ã§Odeumã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«ç™»éŒ²ã™ã‚‹ãƒ¦ãƒ¼ãƒ†ã‚£ãƒªãƒ†ã‚£ã§ã‚る。ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯Webサイトã®å…¨æ–‡æ¤œç´¢ã‚·ã‚¹ãƒ†ãƒ ã‚’構築ã™ã‚‹éš›ã«å½¹ç«‹ã¤ã€‚サãƒãƒ¼ãƒˆã•れるファイルフォーマットã¯ãƒ—レーンテキストã¨HTMLã§ã‚る。サãƒãƒ¼ãƒˆã•れる文字コードã¯US-ASCIIã¨ISO-8859-1ã§ã‚ã‚‹ã€‚å„æ–‡æ›¸ã®URIã«ã¯ãƒ•ァイルã®ãƒ‘ã‚¹ãŒæŒ‡å®šã•ã‚Œã‚‹ã€‚å„æ–‡æ›¸ã«ã¯ã€`title' 㨠`date' ã¨ã„ã†å±žæ€§ãŒä»˜ä¸Žã•れる。既ã«ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ç™»éŒ²ã—ã¦ã‚るファイルを登録ã—よã†ã¨ã—ãŸå ´åˆã€æ›´æ–°æ™‚åˆ»ãŒæ–°ã—ã‘れã°ç™»éŒ²ã•れã€ãã†ã§ãªã‘れã°ç„¡è¦–ã•れる。更新時刻ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã®ä¸­ã® '_mtime' ã¨ã„ã†ã‚µãƒ–データベースã«è¨˜éŒ²ã•れる。スコア情報ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã®ä¸­ã® `_score' ã¨ã„ã†ã‚µãƒ–データベースã«è¨˜éŒ²ã•ã‚Œã‚‹ã€‚ä»¥ä¸‹ã®æ›¸å¼ã§ç”¨ã„る。`name' ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹åã€`dir' ã¯ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªåを指定ã™ã‚‹ã€‚

odidx register [-l file] [-wmax num] [-tsuf sufs] [-hsuf sufs] name [dir]
特定ã®ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªä»¥ä¸‹ã®ãƒ•ァイル群をデータベース登録ã™ã‚‹ã€‚`dir' ãŒçœç•¥ã•れãŸå ´åˆã€ã‚«ãƒ¬ãƒ³ãƒˆãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªãŒæŒ‡å®šã•れる。
odidx relate name
データベースã®å„文書ã«é–¢é€£æ–‡æ›¸æ¤œç´¢ã®ãŸã‚ã®ã‚¹ã‚³ã‚¢æƒ…報を付加ã™ã‚‹ã€‚
odidx purge name
ファイルシステムã«å­˜åœ¨ã—ãªã„文書をデータベースã‹ã‚‰å‰Šé™¤ã™ã‚‹ã€‚

å„オプションã¯ä»¥ä¸‹ã®æ©Ÿèƒ½ã‚’æŒã¤ã€‚

  • -l file : 登録ã™ã¹ãファイルã®ãƒ‘スã®ãƒªã‚¹ãƒˆã‚’ファイルã‹ã‚‰èª­ã¿è¾¼ã‚€ã€‚`-' を指定ã—ãŸå ´åˆã€æ¨™æº–入力ãŒèª­ã¿è¾¼ã¾ã‚Œã‚‹ã€‚
  • -wmax num : ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«æ ¼ç´ã™ã‚‹èªžã®æœ€å¤§æ•°ã‚’指定ã™ã‚‹ã€‚
  • -tsuf sufs : ãƒ—ãƒ¬ãƒ¼ãƒ³ãƒ†ã‚­ã‚¹ãƒˆãƒ•ã‚¡ã‚¤ãƒ«ã®æ‹¡å¼µå­ã‚’ã‚«ãƒ³ãƒžåŒºåˆ‡ã‚Šã§æŒ‡å®šã™ã‚‹ã€‚デフォルト㯠`-tsuf .txt,.text' ã¨åŒæ„ã§ã‚る。
  • -hsuf sufs : HTMLãƒ•ã‚¡ã‚¤ãƒ«ã®æ‹¡å¼µå­ã‚’ã‚«ãƒ³ãƒžåŒºåˆ‡ã‚Šã§æŒ‡å®šã™ã‚‹ã€‚デフォルト㯠`-hsuf .html,.htm' ã¨åŒæ„ã§ã‚る。

ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã¯å‡¦ç†ãŒæ­£å¸¸ã«çµ‚了ã™ã‚Œã° 0 ã‚’è¿”ã—ã€ã‚¨ãƒ©ãƒ¼ãŒã‚れã°ãれ以外ã®å€¤ã‚’è¿”ã—ã¦çµ‚了ã™ã‚‹ã€‚

Odeumã®ã‚³ãƒžãƒ³ãƒ‰ç¾¤ã‚’駆使ã™ã‚‹ã¨ã€å…¨æ–‡æ¤œç´¢ã‚·ã‚¹ãƒ†ãƒ ã‚’ç°¡å˜ã«å®Ÿç¾ã™ã‚‹ã“ã¨ãŒã§ãる。例ãˆã° `/home/mikio' 以下ã«ã‚りã€ã‹ã¤ `.txt' ã‹ `.c' ã‹ `.h' ã¨ã„ã†æŽ¥å°¾è¾žã‚’æŒã¤ãƒ•ァイル群を `casket' ã¨ã„ã†åå‰ã®ã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹ã«ç™»éŒ²ã™ã‚‹ãªã‚‰ã€ä»¥ä¸‹ã®ã‚ˆã†ã«ã™ã‚‹ã€‚

odidx register -tsuf ".txt,.c,.h" -hsuf "" casket /home/mikio

ãã—ã¦ã€`unix' ãŠã‚ˆã³ `posix' ã¨ã„ã†èªžã‚’å«ã‚€æ–‡æ›¸ã‚’検索ã—ã€ä¸Šä½8件を表示ã™ã‚‹ã«ã¯ã€ä»¥ä¸‹ã®ã‚ˆã†ã«ã™ã‚‹ã€‚

odmgr search -max 8 -h casket "unix posix"

`odidx' ã§ç”Ÿæˆã—ãŸãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã¯ã€QDBMã«ä»˜éŒ²ã•れる全文検索ã®ãŸã‚ã®CGIスクリプト `qfts.cgi' ã§ãã®ã¾ã¾åˆ©ç”¨ã™ã‚‹ã“ã¨ãŒã§ãる。


ファイルフォーマット

Depotã®ãƒ•ァイルフォーマット

DepotãŒç®¡ç†ã™ã‚‹ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルã®å†…容ã¯ã€ãƒ˜ãƒƒãƒ€éƒ¨ã€ãƒã‚±ãƒƒãƒˆéƒ¨ã€ãƒ¬ã‚³ãƒ¼ãƒ‰éƒ¨ã®ä¸‰ã¤ã«å¤§åˆ¥ã•れる。

ヘッダ部ã¯ãƒ•ァイルã®å…ˆé ­ã‹ã‚‰ 48 ãƒã‚¤ãƒˆã®å›ºå®šé•·ã§ã¨ã‚‰ã‚Œã€ä»¥ä¸‹ã®æƒ…å ±ãŒè¨˜éŒ²ã•れる。

  1. マジックナンム: オフセット 0 ã‹ã‚‰å§‹ã¾ã‚‹ã€‚ビッグエンディアン用ãªã‚‰æ–‡å­—列 "[DEPOT]\n\f" を内容ã¨ã—ã€ãƒªãƒˆãƒ«ã‚¨ãƒ³ãƒ‡ã‚£ã‚¢ãƒ³ç”¨ãªã‚‰æ–‡å­—列 "[depot]\n\f" を内容ã¨ã™ã‚‹ã€‚
  2. ãƒãƒ¼ã‚¸ãƒ§ãƒ³ç•ªå· : オフセット 12 ã‹ã‚‰å§‹ã¾ã‚‹ã€‚ライブラリã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ç•ªå·ã‚’10進数ã§è¡¨ç¾ã—ãŸæ–‡å­—列を内容ã¨ã™ã‚‹ã€‚
  3. ラッパー用フラグ : オフセット 16 ã‹ã‚‰å§‹ã¾ã‚‹ã€‚`int' åž‹ã®æ•´æ•°ã§ã‚る。
  4. ファイルサイズ : オフセット 24 ã‹ã‚‰å§‹ã¾ã‚‹ã€‚`int' åž‹ã®æ•´æ•°ã§ã‚る。
  5. ãƒã‚±ãƒƒãƒˆé…列ã®è¦ç´ æ•° : オフセット 32 ã‹ã‚‰å§‹ã¾ã‚‹ã€‚`int' åž‹ã®æ•´æ•°ã§ã‚る。
  6. レコード数 : オフセット 40 ã‹ã‚‰å§‹ã¾ã‚‹ã€‚`int' åž‹ã®æ•´æ•°ã§ã‚る。

ãƒã‚±ãƒƒãƒˆéƒ¨ã¯ãƒ˜ãƒƒãƒ€éƒ¨ã®ç›´å¾Œã«ãƒã‚±ãƒƒãƒˆé…列ã®è¦ç´ æ•°ã«å¿œã˜ãŸå¤§ãã•ã§ã¨ã‚‰ã‚Œã€ãƒã‚§ãƒ¼ãƒ³ã®å…ˆé ­è¦ç´ ã®ã‚ªãƒ•セットãŒå„è¦ç´ ã«è¨˜éŒ²ã•れる。

レコード部ã¯ãƒã‚±ãƒƒãƒˆéƒ¨ã®ç›´å¾Œã‹ã‚‰ãƒ•ã‚¡ã‚¤ãƒ«ã®æœ«å°¾ã¾ã§ã‚’å ã‚ã€å„レコードã®ä»¥ä¸‹ã®æƒ…報をæŒã¤è¦ç´ ãŒè¨˜éŒ²ã•れる。

  1. フラグ : `int' åž‹ã®æ•´æ•°ã§ã‚る。
  2. キーã®ç¬¬äºŒãƒãƒƒã‚·ãƒ¥å€¤ : `int' åž‹ã®æ•´æ•°ã§ã‚る。
  3. キーã®ã‚µã‚¤ã‚º : `int' åž‹ã®æ•´æ•°ã§ã‚る。
  4. 値ã®ã‚µã‚¤ã‚º : `int' åž‹ã®æ•´æ•°ã§ã‚る。
  5. パディングã®ã‚µã‚¤ã‚º : `int' åž‹ã®æ•´æ•°ã§ã‚る。
  6. å·¦ã®å­ã®ä½ç½® : `int' åž‹ã®æ•´æ•°ã§ã‚る。
  7. å³ã®å­ã®ä½ç½® : `int' åž‹ã®æ•´æ•°ã§ã‚る。
  8. キーã®å®Ÿãƒ‡ãƒ¼ã‚¿ : キーã®ã‚µã‚¤ã‚ºã§å®šç¾©ã•れる長ã•ã‚’æŒã¤ä¸€é€£ã®ãƒã‚¤ãƒˆã§ã‚る。
  9. 値ã®å®Ÿãƒ‡ãƒ¼ã‚¿ : 値ã®ã‚µã‚¤ã‚ºã§å®šç¾©ã•れる長ã•ã‚’æŒã¤ä¸€é€£ã®ãƒã‚¤ãƒˆã§ã‚る。
  10. パディング : 値ã®ã‚µã‚¤ã‚ºã¨ã‚¢ãƒ©ã‚¤ãƒ³ãƒ¡ãƒ³ãƒˆã«ã‚ˆã‚Šç®—出ã•れる長ã•ã‚’æŒã¤ä¸€é€£ã®ãƒã‚¤ãƒˆã§ã‚る。

Villaã®ãƒ•ァイルフォーマット

Villaã®æ‰±ã†å…¨ã¦ã®ãƒ‡ãƒ¼ã‚¿ã¯Depotã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«è¨˜éŒ²ã•れる。記録ã•れるデータã¯ã€ãƒ¡ã‚¿ãƒ‡ãƒ¼ã‚¿ã¨è«–ç†ãƒšãƒ¼ã‚¸ã«åˆ†é¡žã•れる。論ç†ãƒšãƒ¼ã‚¸ã¯ãƒªãƒ¼ãƒ•ノードã¨éžãƒªãƒ¼ãƒ•ノードã«åˆ†é¡žã•れる。メタデータã¯ãƒ¬ã‚³ãƒ¼ãƒ‰æ•°ç­‰ã®ç®¡ç†æƒ…報を記録ã™ã‚‹ã‚‚ã®ã§ã€ã‚­ãƒ¼ã¨å€¤ã¨ã‚‚ã« `int' åž‹ã§ã‚る。リーフノードã¯ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’ä¿æŒã™ã‚‹ã€‚éžãƒªãƒ¼ãƒ•ノードã¯ãƒšãƒ¼ã‚¸ã‚’å‚ç…§ã™ã‚‹ç–Žã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹ã‚’ä¿æŒã™ã‚‹ã€‚

Villaã¯ã€å°ã•ã„自然数を直列化ã—ã¦æ‰±ã†éš›ã«è¨˜æ†¶é ˜åŸŸã‚’節約ã™ã‚‹ãŸã‚ã«ã€å¯å¤‰é•·æ•´æ•°ãƒ•ォーマット(BER圧縮)を用ã„る。å¯å¤‰é•·æ•´æ•°ã®ã‚ªãƒ–ジェクトã¯ã€é ˜åŸŸã®å…ˆé ­ã‹ã‚‰è§£æžã—ã€å€¤ãŒæ­£ã®ãƒã‚¤ãƒˆã‚’読んã ã‚‰ãã“ã§çµ‚端ã¨ã™ã‚‹ã€‚å„ãƒã‚¤ãƒˆã¯çµ¶å¯¾å€¤ã§è©•価ã•れã€ãƒªãƒˆãƒ«ã‚¨ãƒ³ãƒ‡ã‚£ã‚¢ãƒ³ã®128進数ã¨ã—ã¦ç®—出ã•れる。

レコードã¯ãƒ¦ãƒ¼ã‚¶ãƒ‡ãƒ¼ã‚¿ã®è«–ç†çš„ãªå˜ä½ã§ã‚る。キーãŒé‡è¤‡ã™ã‚‹è«–ç†ãƒ¬ã‚³ãƒ¼ãƒ‰ã¯ç‰©ç†çš„ã«ã¯å˜ä¸€ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã«ã¾ã¨ã‚られる。物ç†ãƒ¬ã‚³ãƒ¼ãƒ‰ã¯ä»¥ä¸‹ã®å½¢å¼ã§ç›´åˆ—化ã•れる。

  1. キーã®ã‚µã‚¤ã‚º : å¯å¤‰é•·æ•´æ•°åž‹ã§ã‚る。
  2. キーã®å®Ÿãƒ‡ãƒ¼ã‚¿ : キーã®ã‚µã‚¤ã‚ºã§å®šç¾©ã•れる長ã•ã‚’æŒã¤ä¸€é€£ã®ãƒã‚¤ãƒˆã§ã‚る。
  3. å€¤ã®æ•° : å¯å¤‰é•·æ•´æ•°åž‹ã§ã‚る。
  4. 値ã®ãƒªã‚¹ãƒˆ : 以下ã®è¡¨ç¾ã‚’å€¤ã®æ•°ã ã‘繰り返ã—ãŸä¸€é€£ã®ãƒã‚¤ãƒˆã§ã‚る。
    1. サイズ : å¯å¤‰é•·æ•´æ•°åž‹ã§ã‚る。
    2. 実データ : サイズã§å®šç¾©ã•れる長ã•ã‚’æŒã¤ä¸€é€£ã®ãƒã‚¤ãƒˆã§ã‚る。

リーフノードã¯ãƒ¬ã‚³ãƒ¼ãƒ‰ã®é›†åˆã‚’æ ¼ç´ã™ã‚‹ãŸã‚ã®ç‰©ç†çš„ãªå˜ä½ã§ã‚る。リーフノード㯠`int' åž‹ã®IDをキーã¨ã—ã€ä»¥ä¸‹ã®å€¤ã‚’æŒã¤ãƒ¬ã‚³ãƒ¼ãƒ‰ã¨ã—ã¦Depotã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«æ ¼ç´ã•れる。レコードã¯å¸¸ã«ã‚­ãƒ¼ã®æ˜‡é †ã«æ•´åˆ—ã—ãŸçŠ¶æ…‹ã§ä¿æŒã•れる。

  1. å‰ã®ãƒªãƒ¼ãƒ•ã®ID : å¯å¤‰é•·æ•´æ•°åž‹ã§ã‚る。
  2. 次ã®ãƒªãƒ¼ãƒ•ã®ID : å¯å¤‰é•·æ•´æ•°åž‹ã§ã‚る。
  3. レコードã®ãƒªã‚¹ãƒˆ : 直列化ã—ãŸãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’連çµã—ãŸã‚‚ã®ã€‚

インデックスã¯ãƒšãƒ¼ã‚¸ã‚’探索ã™ã‚‹ãŸã‚ã®ãƒã‚¤ãƒ³ã‚¿ã®è«–ç†çš„ãªå˜ä½ã§ã‚る。インデックスã¯ä»¥ä¸‹ã®å½¢å¼ã§ç›´åˆ—化ã•れる。

  1. å‚ç…§å…ˆã®ãƒšãƒ¼ã‚¸ã®ID : å¯å¤‰é•·æ•´æ•°åž‹ã§ã‚る。
  2. キーã®ã‚µã‚¤ã‚º : å¯å¤‰é•·æ•´æ•°åž‹ã§ã‚る。
  3. キーã®å®Ÿãƒ‡ãƒ¼ã‚¿ : キーã®ã‚µã‚¤ã‚ºã§å®šç¾©ã•れる長ã•ã‚’æŒã¤ä¸€é€£ã®ãƒã‚¤ãƒˆã§ã‚る。

éžãƒªãƒ¼ãƒ•ノードã¯ã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹ã®é›†åˆã‚’æ ¼ç´ã™ã‚‹ãŸã‚ã®ç‰©ç†çš„ãªå˜ä½ã§ã‚る。éžãƒªãƒ¼ãƒ•ノード㯠`int' åž‹ã®IDをキーã¨ã—ã€ä»¥ä¸‹ã®å€¤ã‚’æŒã¤ãƒ¬ã‚³ãƒ¼ãƒ‰ã¨ã—ã¦Depotã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«æ ¼ç´ã•れる。インデックスã¯å¸¸ã«ã‚­ãƒ¼ã®æ˜‡é †ã«æ•´åˆ—ã—ãŸçŠ¶æ…‹ã§ä¿æŒã•れる。

  1. 最åˆã®å­ãƒŽãƒ¼ãƒ‰ã®ID : å¯å¤‰é•·æ•´æ•°åž‹ã§ã‚る。
  2. インデックスã®ãƒªã‚¹ãƒˆ : 直列化ã—ãŸã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹ã‚’連çµã—ãŸã‚‚ã®ã€‚

注記

データベースファイルã¯ã‚¹ãƒ‘ースã§ã¯ãªã„ã®ã§ã€é€šå¸¸ã®ãƒ•ァイルã¨åŒæ§˜ã«è¤‡è£½ç­‰ã®æ“作を行ã†ã“ã¨ãŒã§ãる。Depotã¯ãƒã‚¤ãƒˆã‚ªãƒ¼ãƒ€ã®èª¿æ•´ã‚’ã—ãªã„ã§ãƒ•ァイルã®èª­ã¿æ›¸ãを行ã£ã¦ã„ã‚‹ã®ã§ã€ãƒã‚¤ãƒˆã‚ªãƒ¼ãƒ€ã®ç•°ãªã‚‹ç’°å¢ƒã«ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルを移設ã—ã¦ã‚‚ãã®ã¾ã¾ã§ã¯åˆ©ç”¨ã§ããªã„。

Depotã‚„Villaã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルをãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã§é…布ã™ã‚‹éš›ã«ã¯ã€MIMEタイプを `application/x-qdbm' ã«ã—ã¦ã»ã—ã„。ファイルåã®æŽ¥å°¾è¾žã¯ `.qdb' ã«ã—ã¦ã»ã—ã„。Curiaã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã‚’ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã§é…布ã™ã‚‹éš›ã«ã¯ã€TARå½¢å¼ç­‰ã‚’用ã„ãŸã‚¢ãƒ¼ã‚«ã‚¤ãƒ–ã«å¤‰æ›ã—ã¦è¡Œã†ã“ã¨ãŒã§ãる。

データベースファイルã®ãƒžã‚¸ãƒƒã‚¯ãƒŠãƒ³ãƒã‚’ `file' コマンドã«è­˜åˆ¥ã•ã›ãŸã„å ´åˆã¯ã€`magic' ファイルã«ä»¥ä¸‹ã®è¡Œã‚’追記ã™ã‚‹ã¨ã‚ˆã„。

0       string          [DEPOT]\n\f     QDBM, big endian
>12     string          x               \b, version=%s
>19     byte            ^1              \b, Hash
>19     byte            &1              \b, B+ tree
>19     byte            &2              \b (deflated:ZLIB)
>19     byte            &4              \b (deflated:LZO)
>19     byte            &8              \b (deflated:BZIP2)
>24     belong          x               \b, filesize=%d
>32     belong          x               \b, buckets=%d
>40     belong          x               \b, records=%d
0       string          [depot]\n\f     QDBM, little endian
>12     string          x               \b, version=%s
>16     byte            ^1              \b, Hash
>16     byte            &1              \b, B+ tree
>16     byte            &2              \b (deflated:ZLIB)
>16     byte            &4              \b (deflated:LZO)
>16     byte            &8              \b (deflated:BZIP2)
>24     lelong          x               \b, filesize=%d
>32     lelong          x               \b, buckets=%d
>40     lelong          x               \b, records=%d

ç§»æ¤æ–¹æ³•

QDBMã¯POSIX互æ›ã®å…¨ã¦ã®ãƒ—ラットフォームã§å‹•作ã™ã‚‹ã“ã¨ã‚’目標ã¨ã—ã¦ã„る。ãŸã ã—ã€ã„ãã¤ã‹ã®APIãŒå®Ÿè£…ã•れã¦ã„ãªã„プラットフォームã§ã‚‚動作ã™ã‚‹ã“ã¨ãŒæœ›ã¾ã—ã„。ã¾ãŸã€GCC以外ã®ã‚³ãƒ³ãƒ‘イラを利用ã—ã¦ã‚‚ビルドãŒã§ãã‚‹ã“ã¨ãŒæœ›ã¾ã—ã„。様々ãªãƒ—ラットフォームã¸ã®ç§»æ¤ä½œæ¥­ã¯ã€æ–°ã—ã„ `Makefile' を追加ã—ãŸã‚Šã‚½ãƒ¼ã‚¹ãƒ•ァイルã®ä¸€éƒ¨ã‚’修正ã—ãŸã‚Šã™ã‚‹ã“ã¨ã«ã‚ˆã£ã¦ãªã•れる。C言語ã®APIã§ã‚れã°ã€ãŠãらã以下ã®ãƒ•ァイルã®ã„ãã¤ã‹ã‚’修正ã™ã‚‹ã“ã¨ã«ãªã‚‹ã€‚ã‚‚ã—ãã¯ãã‚Œã‚‰ã‚’åŸºã«æ–°ã—ã„ファイルを作ã£ã¦ã‚‚よã„。

  • Makefile.in : `./configure' ã«åˆ©ç”¨ã•れã€`Makefile' ã®ãƒ™ãƒ¼ã‚¹ã¨ãªã‚‹ã€‚
  • myconf.h : システムä¾å­˜ã®è¨­å®šãƒ•ァイル。
  • depot.h : 基本APIã®ãƒ˜ãƒƒãƒ€ã€‚
  • curia.h : æ‹¡å¼µAPIã®ãƒ˜ãƒƒãƒ€ã€‚
  • relic.h : NDBM互æ›APIã®ãƒ˜ãƒƒãƒ€ã€‚
  • hovel.h : GDBM互æ›APIã®ãƒ˜ãƒƒãƒ€ã€‚
  • cabin.h : ユーティリティAPIã®ãƒ˜ãƒƒãƒ€ã€‚
  • villa.h : 上級APIã®ãƒ˜ãƒƒãƒ€ã€‚
  • vista.h : 拡張上級APIã®ãƒ˜ãƒƒãƒ€ã€‚
  • odeum.h : 転置APIã®ãƒ˜ãƒƒãƒ€ã€‚
  • myconf.c : システムä¾å­˜ã®å®Ÿè£…。
  • depot.c : 基本APIã®å®Ÿè£…。
  • curia.c : æ‹¡å¼µAPIã®å®Ÿè£…。
  • relic.c : NDBM互æ›APIã®å®Ÿè£…。
  • hovel.c : GDBM互æ›APIã®å®Ÿè£…。
  • cabin.c : ユーティリティAPIã®å®Ÿè£…。
  • villa.c : 上級APIã®å®Ÿè£…。
  • vista.c : 拡張上級APIã®å®Ÿè£…。
  • odeum.c : 転置APIã®å®Ÿè£…。

`fcntl' コールã«ã‚ˆã‚‹ãƒ•ァイルロックãŒã‚µãƒãƒ¼ãƒˆã•れã¦ã„ãªã„プラットフォームã§ã¯ã€`Makefile' ã§å®šç¾©ã•れる `CFLAGS' マクロ㫠`-DMYNOLOCK' を追加ã™ã‚‹ã¨ã‚ˆã„。ãã®éš›ã«ã¯ãƒ—ãƒ­ã‚»ã‚¹é–“ã®æŽ’ä»–åˆ¶å¾¡ã‚’è¡Œã†åˆ¥ã®æ–¹æ³•を考ãˆã‚‹å¿…è¦ãŒã‚ã‚‹ã€‚åŒæ§˜ã«ã€`mmap' コールãŒãªã„プラットフォームã§ã¯ã€`CFLAGS' ã« `-DMYNOMMAP' を追加ã™ã‚‹ã¨ã‚ˆã„。`mmap' ã«é–¢ã—ã¦ã¯ `malloc' 等を用ã„ãŸã‚¨ãƒŸãƒ¥ãƒ¬ãƒ¼ã‚·ãƒ§ãƒ³ãŒç”¨æ„ã•れã¦ã„る。ãã®ä»–ã®ã‚·ã‚¹ãƒ†ãƒ ã‚³ãƒ¼ãƒ«ãŒå®Ÿè£…ã•れã¦ã„ãªã„å ´åˆã¯ã€`myconf.h' 㨠`myconf.c' を修正ã—ã¦è©²å½“ã®ã‚·ã‚¹ãƒ†ãƒ ã‚³ãƒ¼ãƒ«ã®ã‚¨ãƒŸãƒ¥ãƒ¬ãƒ¼ã‚·ãƒ§ãƒ³ã‚’行ãˆã°ã‚ˆã„。

C++用ã®APIã§ã¯POSIXスレッドを使ã£ã¦ã„ã‚‹ã®ã§ã€ãã®ãƒ‘ッケージãŒå®Ÿè£…ã•れã¦ã„ãªã„環境ã«ã¯C++用APIã¯ç§»æ¤ã§ããªã„。Java用ã®APIã§ã¯JNIを使ã£ã¦ã„ã‚‹ã®ã§ã€ãã®ãƒ˜ãƒƒãƒ€ã‚„ライブラリã®å ´æ‰€ã«æ³¨æ„ã™ã¹ãã§ã‚る。ã¾ãŸã€`long long' ã‚„ `int64' ã¨ã„ã£ãŸåž‹å®šç¾©ã«ã‚‚注æ„ã™ã¹ãã§ã‚る。Perlã‚„Ruby用ã®APIã§ã¯å„々ã®è¨€èªžå‡¦ç†ç³»ã§ç”¨æ„ã•れãŸãƒ“ルドコマンドを用ã„ã¦ã„ã‚‹ã®ã§ã€ãã®ä»•様ã«ç²¾é€šã™ã¹ãã§ã‚る。


ãƒã‚°

QDBMã®å„文書ã¯è‹±èªžã‚’æ¯å›½èªžã¨ã™ã‚‹äººé”ã«ã‚ˆã£ã¦æ ¡æ­£ã•れるã¹ãã§ã‚る。

segmentation faultã«ã‚ˆã‚‹ã‚¯ãƒ©ãƒƒã‚·ãƒ¥ã€äºˆæœŸã›ã¬ãƒ‡ãƒ¼ã‚¿ã®æ¶ˆå¤±ç­‰ã®ä¸æ•´åˆã€ãƒ¡ãƒ¢ãƒªãƒªãƒ¼ã‚¯ã€ãã®ä»–諸々ã®ãƒã‚°ã«é–¢ã—ã¦ã€æ—¢çŸ¥ã®ã‚‚ã®ã§æœªä¿®æ­£ã®ã‚‚ã®ã¯ãªã„。

ãƒã‚°ã‚’発見ã—ãŸã‚‰ã€æ˜¯éžã¨ã‚‚作者ã«ãƒ•ィードãƒãƒƒã‚¯ã—ã¦ã»ã—ã„。ãã®éš›ã€QDBMã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã¨ã€åˆ©ç”¨ç’°å¢ƒã®OSã¨ã‚³ãƒ³ãƒ‘イラã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã‚‚æ•™ãˆã¦ã»ã—ã„。

1.7.13よりå‰ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã®QDBMã§ä½œæˆã—ãŸãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã¯ã€ãれ以後ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã¨äº’æ›æ€§ãŒãªã„。


よãèžã‹ã‚Œã‚‹è³ªå•

Q. : QDBMã¯SQLをサãƒãƒ¼ãƒˆã™ã‚‹ã‹ã€‚
A. : QDBMã¯SQLをサãƒãƒ¼ãƒˆã—ãªã„。QDBMã¯RDBMS(関係データベース管ç†ã‚·ã‚¹ãƒ†ãƒ ï¼‰ã§ã¯ãªã„。組ã¿è¾¼ã¿ã®RDBMSを求ã‚ã‚‹ãªã‚‰ã€SQLiteãªã©ã‚’利用ã™ã‚‹ã¨ã‚ˆã„。
Q. : çµå±€ã®ã¨ã“ã‚ã€GDBM(NDBMã€SDBMã€Berkeley DB)ã¨ã©ã†é•ã†ã®ã‹ã€‚
A. : 処ç†ãŒé€Ÿã„。データベースファイルãŒå°ã•ã„。APIãŒç°¡æ½”ã§ã‚る。特筆ã™ã¹ãã¯ã€ãƒ¬ã‚³ãƒ¼ãƒ‰ã®ä¸Šæ›¸ãを繰り返ã™å ´åˆã®æ™‚é–“çš„ãŠã‚ˆã³ç©ºé–“的効率ãŒã¨ã¦ã‚‚よãã€å®Ÿç”¨ä¸Šã®ã‚¹ã‚±ãƒ¼ãƒ©ãƒ“リティãŒé«˜ã„ã“ã¨ã§ã‚る。ã¾ãŸã€ãƒ¬ã‚³ãƒ¼ãƒ‰æ•°ãŒ100万を越ãˆã‚‹ã‚ˆã†ãªå¤§è¦æ¨¡ãªãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’構築ã™ã‚‹éš›ã«ã‚‚ã€å‡¦ç†ãŒæ¥µç«¯ã«é…ããªã£ãŸã‚Šã€ãƒ•ァイルã®ã‚µã‚¤ã‚ºãŒæ¥µç«¯ã«å¤§ãããªã£ãŸã‚Šã—ãªã„。ã¨ã¯ã„ãˆã€ç”¨é€”ã«ã‚ˆã£ã¦ã¯ä»–ã®DBMã‚„DBMSã‚’ä½¿ã†æ–¹ãŒé©åˆ‡ã‹ã‚‚ã—れãªã„ã®ã§ã€å„è‡ªã§æ€§èƒ½ã‚„æ©Ÿèƒ½ã®æ¯”較をã—ã¦ã¿ã¦ã»ã—ã„。
Q. : å‚考文献ã¯ä½•ã‹ã€‚
A. : QDBMã®å„種アルゴリズムã¯ã€ä¸»ã«Ahoä»–ã® `Data Structures and Algorithms'(邦題ã¯ã€Œãƒ‡ãƒ¼ã‚¿æ§‹é€ ã¨ã‚¢ãƒ«ã‚´ãƒªã‚ºãƒ ã€ï¼‰ãŠã‚ˆã³Sedgewickã® `Algorithms in C'(邦題ã¯ã€Œã‚¢ãƒ«ã‚´ãƒªã‚ºãƒ Cã€ï¼‰ã®è¨˜è¿°ã«åŸºç¤Žã‚’ç½®ã„ã¦ã„る。
Q. : ã©ã®APIを使ãˆã°ã‚ˆã„ã®ã‹ã€‚
A. : ãƒ¬ã‚³ãƒ¼ãƒ‰ã®æ¤œç´¢ãŒå®Œå…¨ä¸€è‡´ã ã‘ã§æ¸ˆã‚€ã®ãªã‚‰ã€Depotを試ã™ã¨ã‚ˆã„。ãã®è¦æ¨¡ãŒå¤§ãã„ãªã‚‰ã€Curiaを試ã™ã¨ã‚ˆã„。レコードを順åºã«åŸºã¥ã„ã¦å‚ç…§ã—ãŸã„ãªã‚‰ã€Villaを試ã™ã¨ã‚ˆã„。ãã®è¦æ¨¡ãŒå¤§ãã„ãªã‚‰ã€Vistaを試ã™ã¨ã‚ˆã„。最大ã®ãƒ¬ã‚³ãƒ¼ãƒ‰æ•°ã‚’追求ã™ã‚‹ãªã‚‰ã€ZLIBã‹LZOを有効ã«ã—ã¦QDBMをビルドã—ã€ãã®ä¸Šã§Vistaを用ã„ã‚‹ã®ãŒã‚ˆã„。
Q. : アプリケーションã®è‰¯ã„サンプルコードã¯ã‚ã‚‹ã‹ã€‚
A. : å„APIã®ã‚³ãƒžãƒ³ãƒ‰ã®ã‚½ãƒ¼ã‚¹ã‚³ãƒ¼ãƒ‰ã‚’å‚考ã«ã—ã¦ã»ã—ã„。`dptsv.c' 㨠`crtsv.c' 㨠`vltsv.c' ãŒæœ€ã‚‚ç°¡æ½”ã§ã‚る。
Q. : データベースãŒå£Šã‚ŒãŸã®ã ãŒã€ã©ã†ã—ã¦ã‹ã€‚
A. : 大抵ã®å ´åˆã€ã‚ãªãŸã®ã‚¢ãƒ—リケーションãŒãã¡ã‚“ã¨ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’é–‰ã˜ã¦ã„ãªã„ã®ãŒåŽŸå› ã§ã‚る。デーモンプロセスã§ã‚ã‚ã†ãŒã€CGIスクリプトã§ã‚ã‚ã†ãŒã€ã‚¢ãƒ—リケーションãŒçµ‚了ã™ã‚‹éš›ã«ã¯å¿…ãšãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’é–‰ã˜ãªã‘れã°ãªã‚‰ãªã„。ãªãŠã€CGIã®ãƒ—ロセスã¯SIGPIPEã‚„SIGTERMã«ã‚ˆã£ã¦æ®ºã•れるã“ã¨ãŒã‚ã‚‹ã“ã¨ã«ã‚‚ç•™æ„ã™ã¹ãã§ã‚る。
Q. : QDBMã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã¯ã©ã®ãらã„堅牢ãªã®ã‹ã€‚
A. : QDBMã¯çµ¶å¯¾çš„ãªå …牢性ã¯ä¿è¨¼ã—ãªã„ã€‚ã‚ªãƒšãƒ¬ãƒ¼ãƒ†ã‚£ãƒ³ã‚°ã‚·ã‚¹ãƒ†ãƒ ãŒæš´èµ°ã—ãŸéš›ã«ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãŒå£Šã‚Œã‚‹å¯èƒ½æ€§ãŒã‚る。Villaã®ãƒˆãƒ©ãƒ³ã‚¶ã‚¯ã‚·ãƒ§ãƒ³ã¯ã‚¢ãƒ—ãƒªã‚±ãƒ¼ã‚·ãƒ§ãƒ³ã®æš´èµ°ã‹ã‚‰ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’ä¿è­·ã™ã‚‹ã“ã¨ãŒã§ãã‚‹ãŒã€ã‚ªãƒšãƒ¬ãƒ¼ãƒ†ã‚£ãƒ³ã‚°ã‚·ã‚¹ãƒ†ãƒ ã®æš´èµ°ã«ã¯å¯¾å‡¦ã§ããªã„。ã—ãŸãŒã£ã¦ã€ãƒŸãƒƒã‚·ãƒ§ãƒ³ã‚¯ãƒªãƒ†ã‚£ã‚«ãƒ«ãªç”¨é€”ã«QDBMを利用ã™ã‚‹å ´åˆã¯ã€ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®å¤šé‡åŒ–を考慮ã™ã¹ãã§ã‚る。
Q. : Depotã¨Curiaã®ã‚¢ãƒ©ã‚¤ãƒ³ãƒ¡ãƒ³ãƒˆã®ä½¿ã„æ–¹ãŒã‚ˆãã‚ã‹ã‚‰ãªã„ãŒã€‚
A. : 上書ãモードや連çµãƒ¢ãƒ¼ãƒ‰ã§ã®æ›¸ãè¾¼ã¿ã‚’繰り返ã™å ´åˆã«ã€ã‚¢ãƒ©ã‚¤ãƒ³ãƒ¡ãƒ³ãƒˆã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルã®ã‚µã‚¤ã‚ºãŒæ€¥æ¿€ã«å¤§ãããªã‚‹ã®ã‚’防ã。アラインメントã®é©åˆ‡ãªã‚µã‚¤ã‚ºã¯ã‚¢ãƒ—リケーションã«ã‚ˆã£ã¦ç•°ãªã‚‹ã®ã§ã€å„自ã§å®Ÿé¨“ã—ã¦ã¿ã¦ã»ã—ã„。ã•ã—ã‚ãŸã‚Šã¯32ãらã„ã«ã—ã¦ãŠãã¨ã‚ˆã„。
Q. : Villaã®æ€§èƒ½ãƒ‘ラメータã®èª¿æ•´ãŒã‚ˆãã‚ã‹ã‚‰ãªã„ãŒã€‚
A. : レコードを順番ã«å‚ç…§ã™ã‚‹ã“ã¨ãŒå¤šã„ãªã‚‰ã°ã€`lrecmax' 㨠`nidxmax' をより大ããã—ãŸæ–¹ãŒã‚ˆã„。レコードを無作為ã«å‚ç…§ã™ã‚‹ã“ã¨ãŒå¤šã„ãªã‚‰ã°ã€ãれらã¯å°ã•ãã—ãŸæ–¹ãŒã‚ˆã„。RAMã«ä½™è£•ãŒã‚ã‚‹ãªã‚‰ã°ã€`lcnum' 㨠`ncnum' を増やã™ã¨æ€§èƒ½ãŒã‹ãªã‚Šå‘上ã™ã‚‹ã€‚ZLIBã‚„LZOã‚„BZIP2を有効化ã—ãŸå ´åˆã€`lrecmax' を大ããã—ãŸæ–¹ãŒåœ§ç¸®åŠ¹çŽ‡ãŒã‚ˆããªã‚‹ã€‚
Q. : Villaã®åœ§ç¸®æ–¹å¼ã¨ã—ã¦ã¯ZLIBã¨LZOã¨BZIP2ã®ã©ã‚ŒãŒã‚ˆã„ã®ã‹ã€‚
A. : åœ§ç¸®çŽ‡ãŒæœ€ã‚‚良ã„ã®ã¯BZIP2ã§ã€å‡¦ç†é€Ÿåº¦ãŒæœ€ã‚‚高ã„ã®ã¯LZOã§ã€ZLIBã¯ãã®ä¸­é–“çš„ãªç‰¹æ€§ã‚’æŒã¤ã€‚特ã«ç†ç”±ãŒãªã„é™ã‚Šã¯ZLIBを使ã†ã¨ã‚ˆã„。ãŸã ã—ã€æ›´æ–°ãŒé »ç¹ãªãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«ã¯LZOãŒé©åˆ‡ã§ã€æ›´æ–°ãŒã»ã¨ã‚“ã©ãªã„ãªã‚‰ã°BZIP2ãŒé©åˆ‡ã§ã‚る。圧縮ã—ãªã„ã¨ã„ã†é¸æŠžè‚¢ã‚ˆã‚Šã¯LZOã‚’ä½¿ã†æ–¹ãŒã‚ˆã„。LZOã®ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã¯GNU GPLã§ã‚ã‚‹ã“ã¨ã«æ³¨æ„ã™ã‚‹ã“ã¨ã€‚
Q. : スパースファイルã¨ã¯ä½•ã‹ã€‚
A. : ãƒ›ãƒ¼ãƒ«ï¼ˆä¸€åº¦ã‚‚ãƒ‡ãƒ¼ã‚¿ãŒæ›¸ãè¾¼ã¾ã‚Œã¦ã„ãªã„ブロック)ãŒã‚るファイルã®ã“ã¨ã§ã‚る。ファイルシステムãŒã‚¹ãƒ‘ースファイルをサãƒãƒ¼ãƒˆã—ã¦ã„ã‚‹å ´åˆã€ãƒ›ãƒ¼ãƒ«ã¯ç‰©ç†çš„ãªè¨˜æ†¶è£…ç½®ã«å‰²ã‚Šå½“ã¦ã‚‰ã‚Œãªã„。QDBMã§ã¯ã€DP_OSPARSEãªã©ã®ãƒ•ラグを用ã„ã‚‹ã¨ã€ãƒãƒƒã‚·ãƒ¥ã®ãƒã‚±ãƒƒãƒˆé…列ã¯åˆæœŸåŒ–ã•れãšã«ãƒ›ãƒ¼ãƒ«ã¨ãªã‚‹ã€‚ã“ã®ã“ã¨ã‚’利用ã—ã¦ã€éžå¸¸ã«å·¨å¤§ãªãƒãƒƒã‚·ãƒ¥è¡¨ã‚’実ç¾ã™ã‚‹ã“ã¨ãŒã§ãる。ãŸã ã—ã€ãã®æ€§èƒ½ã¯ãƒ•ァイルシステムã®è¨­å®šã«å¼·ãä¾å­˜ã™ã‚‹ã€‚
Q. : ãªãœDepotã¨Curiaã«ã¯ãƒˆãƒ©ãƒ³ã‚¶ã‚¯ã‚·ãƒ§ãƒ³æ©Ÿèƒ½ãŒãªã„ã®ã‹ã€‚
A. : アプリケーションãŒç‹¬è‡ªã®ãƒˆãƒ©ãƒ³ã‚¶ã‚¯ã‚·ãƒ§ãƒ³æ©Ÿèƒ½ã‚’実装ã—ã¦ã„ã‚‹å ´åˆã«ã¯ã€ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹å†…部ã®ãƒˆãƒ©ãƒ³ã‚¶ã‚¯ã‚·ãƒ§ãƒ³ã¯é‚ªé­”ã«ãªã‚‹ã‹ã‚‰ã§ã‚る。トランザクションã¯Cabinã®ãƒžãƒƒãƒ—を使ãˆã°ç°¡å˜ã«å®Ÿè£…ã§ãる。
Q. : 性能を引ã出ã™ã‚·ã‚¹ãƒ†ãƒ ã®è¨­å®šã¯ã©ã†ã§ã‚ã‚‹ã‹ã€‚
A. : データベースã®ã‚µã‚¤ã‚ºã¨åŒç­‰ä»¥ä¸Šã®RAMã‚’ãƒžã‚·ãƒ³ã«æ­è¼‰ã™ã‚‹ã“ã¨ãŒæœ›ã¾ã—ã„。ãã—ã¦ã€I/Oãƒãƒƒãƒ•ã‚¡ã®ã‚µã‚¤ã‚ºã‚’大ããã—ã€ãƒ€ãƒ¼ãƒ†ã‚£ãƒãƒƒãƒ•ァをフラッシュã™ã‚‹é »åº¦ãŒå°‘ãªãã™ã‚‹ã‚ˆã†ã«è¨­å®šã™ã‚‹ã¨ã‚ˆã„。ファイルシステムã®é¸æŠžã‚‚é‡è¦ã§ã‚る。Linux上ã§ã¯ã€é€šå¸¸ã¯EXT2ãŒæœ€é«˜é€Ÿã§ã‚ã‚‹ãŒã€EXT3ã® `writeback' ãƒ¢ãƒ¼ãƒ‰ã®æ–¹ãŒé€Ÿã„ã“ã¨ã‚‚ã‚る。ReiserFSã¯ãれãªã‚Šã§ã‚る。EXT3ã®ãã®ä»–ã®ãƒ¢ãƒ¼ãƒ‰ã¯ã‹ãªã‚Šé…ã„。他ã®ãƒ•ァイルシステムã«é–¢ã—ã¦ã¯å„自ã§å®Ÿé¨“ã—ã¦ã¿ã¦ã»ã—ã„。
Q. : `gcc' ã®ä»£ã‚り㫠`cc' を使ã£ã¦ãƒ“ルドã§ãã‚‹ã‹ã€‚
A. : `LTmakefile' を使ãˆã°ã§ãる。
Q. : Visual C++を使ã£ã¦ãƒ“ルドã§ãã‚‹ã‹ã€‚
A. : ã§ãる。`Makefile' ã®ä»£ã‚り㫠`VCmakefile' を使ã†ã“ã¨ã€‚
Q. : ä»–ã«QDBMを利用ã§ãる言語ã¯ã‚ã‚‹ã‹ã€‚
A. : PHPã€Scheme(Gauche)ã€OCaml用ã®ã‚¤ãƒ³ã‚¿ãƒ•ã‚§ãƒ¼ã‚¹ãŒæ—¢ã«å…¬é–‹ã•れã¦ã„るよã†ã§ã‚る。ãれ以外ã®è¨€èªžã«ã¤ã„ã¦ã¯ã€å¿…è¦ãªã‚‰è‡ªåˆ†ã§ä½œã£ã¦ã»ã—ã„。
Q. : 「QDBMã€ã¨ã¯ã©ã†ã„ã†æ„味ãªã®ã‹ã€‚
A. : 「QDBMã€ã¯ã€ŒQuick Database Managerã€ã®ç•¥ã§ã‚る。高速ã«å‹•作ã™ã‚‹ã¨ã„ã†æ„味ã¨ã€ã‚¢ãƒ—リケーションã®é–‹ç™ºãŒè¿…速ã«ã§ãã‚‹ã¨ã„ã†æ„味ãŒè¾¼ã‚られã¦ã„る。
Q. : å„APIã®åå‰ã¯ã©ã†ã„ã†æ„味ãªã®ã‹ã€‚ã©ã†ç™ºéŸ³ã™ã‚‹ã®ã‹ã€‚
A. : 5文字ã®è‹±å˜èªžã‹ã‚‰é©å½“ã«é¸æŠžã—ãŸã ã‘ã§ã€æ·±ã„æ„味ã¯ãªã„。ãªãŠã€ã€Œdepotã€ã¯ã€ç©ºæ¸¯ã€å€‰åº«ã€è£œçµ¦æ‰€ãªã©ã€ç‰©è³ªãŒé›†ã¾ã‚‹å ´æ‰€ã‚’æ„味ã™ã‚‹ã‚‰ã—ã„。発音を片仮åã§è¡¨ç¾ã™ã‚‹ãªã‚‰ã€Œãƒ‡ã‚£ãƒ¼ãƒã‚¥ã€ãŒå¦¥å½“ã ã‚ã†ã€‚「curiaã€ã¯ã€å®®å»·ã€æ³•å»·ãªã©ã€æ¨©å¨ãŒé›†ã¾ã‚‹å ´æ‰€ã‚’æ„味ã™ã‚‹ã‚‰ã—ã„。発音を片仮åã§è¡¨ç¾ã™ã‚‹ãªã‚‰ã€Œã‚­ãƒ¥ãƒªã‚¢ã€ãŒå¦¥å½“ã ã‚ã†ã€‚「relicã€ã¯ã€éºç‰©ã€éºè·¡ãªã©ã€éŽåŽ»ã®æ®‹éª¸ã‚’æ„味ã™ã‚‹ã‚‰ã—ã„。発音を片仮åã§è¡¨ç¾ã™ã‚‹ãªã‚‰ã€Œãƒ¬ãƒªãƒƒã‚¯ã€ãŒå¦¥å½“ã ã‚ã†ã€‚「hovelã€ã¯ã€å°å±‹ã€ç‰©ç½®ã€é›¢ã‚Œå®¶ãªã©ã€ç²—末ãªå»ºç‰©ã‚’æ„味ã™ã‚‹ã‚‰ã—ã„。発音を片仮åã§è¡¨ç¾ã™ã‚‹ãªã‚‰ã€Œãƒãƒ´ãƒ«ã€ãŒå¦¥å½“ã ã‚ã†ã€‚「cabinã€ã¯ã€æ©Ÿå®¤ã€å®¢å®¤ã€å°å±‹ãªã©ã€ç°¡æ˜“çš„ãªå±…ä½ç©ºé–“ã‚’æ„味ã™ã‚‹ã‚‰ã—ã„。発音を片仮åã§è¡¨ç¾ã™ã‚‹ãªã‚‰ã€Œã‚­ãƒ£ãƒ“ンã€ãŒå¦¥å½“ã ã‚ã†ã€‚「villaã€ã¯ã€åˆ¥è˜ã€éƒŠå¤–ä½å®…ãªã©ã€éƒ½ä¼šé¢¨ã§ãªã„ä½å±…ã‚’æ„味ã™ã‚‹ã‚‰ã—ã„。発音を片仮åã§è¡¨ç¾ã™ã‚‹ãªã‚‰ã€Œãƒ´ã‚£ãƒ©ã€ãŒå¦¥å½“ã ã‚ã†ã€‚「vistaã€ã¯ã€äºˆæƒ³ã€å±•望ãªã©ã€é ãを見渡ã™ã“ã¨ã‚’æ„味ã™ã‚‹ã‚‰ã—ã„。発音を片仮åã§è¡¨ç¾ã™ã‚‹ãªã‚‰ã€Œãƒ´ã‚£ã‚¹ã‚¿ã€ãŒå¦¥å½“ã ã‚ã†ã€‚「odeumã€ã¯ã€éŸ³æ¥½å ‚ã€åЇ場ãªã©ã€éŸ³æ¥½ã‚„è©©åŸã‚’行ã†å»ºç‰©ã‚’æ„味ã™ã‚‹ã‚‰ã—ã„。発音を片仮åã§è¡¨ç¾ã™ã‚‹ãªã‚‰ã€Œã‚ªãƒ‡ã‚£ã‚¢ãƒ ã€ãŒå¦¥å½“ã ã‚ã†ã€‚

ライセンス

QDBMã¯ãƒ•リーソフトウェアã§ã‚る。ã‚ãªãŸã¯ã€Free Software FoundationãŒå…¬è¡¨ã—ãŸGNU Lesser General Public Licenseã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³2.1ã‚ã‚‹ã„ã¯ãれ以é™ã®å„ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã®ä¸­ã‹ã‚‰ã„ãšã‚Œã‹ã‚’é¸æŠžã—ã€ãã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ãŒå®šã‚ã‚‹æ¡é …ã«å¾“ã£ã¦QDBMã‚’å†é ’布ã¾ãŸã¯å¤‰æ›´ã™ã‚‹ã“ã¨ãŒã§ãる。

QDBMã¯æœ‰ç”¨ã§ã‚ã‚‹ã¨æ€ã‚れるãŒã€é ’布ã«ã‚ãŸã£ã¦ã¯ã€å¸‚場性åŠã³ç‰¹å®šç›®çš„é©åˆæ€§ã«ã¤ã„ã¦ã®æš—é»™ã®ä¿è¨¼ã‚’å«ã‚ã¦ã€ã„ã‹ãªã‚‹ä¿è¨¼ã‚‚行ãªã‚ãªã„。詳細ã«ã¤ã„ã¦ã¯GNU Lesser General Public Licenseを読んã§ã»ã—ã„。

ã‚ãªãŸã¯ã€QDBMã¨ä¸€ç·’ã«GNU Lesser General Public Licenseã®å†™ã—ã‚’å—ã‘å–ã£ã¦ã„ã‚‹ã¯ãšã§ã‚る(`COPYING' ファイルをå‚照)。ãã†ã§ãªã„å ´åˆã¯ã€Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA ã¸é€£çµ¡ã—ã¦ã»ã—ã„。

QDBMã¯å¹³æž—幹雄ãŒä½œæˆã—ãŸã€‚作者ã¨é€£çµ¡ã‚’ã¨ã‚‹ã«ã¯ã€`mikio@fallabs.com' å®›ã«é›»å­ãƒ¡ãƒ¼ãƒ«ã‚’é€ã£ã¦ã»ã—ã„。


qdbm-1.8.78/doc/index.ja.html0000644000175000017500000002054511426315676014720 0ustar mikiomikio データベースライブラリ QDBM

QDBM: Quick Database Manager

Copyright (C) 2000-2007 Mikio Hirabayashi
Last Update: Thu, 26 Oct 2006 15:00:20 +0900

概è¦

QDBMã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’扱ã†ãƒ«ãƒ¼ãƒãƒ³ç¾¤ã®ãƒ©ã‚¤ãƒ–ラリã§ã™ã€‚データベースã¨ã„ã£ã¦ã‚‚å˜ç´”ãªã‚‚ã®ã§ã€ã‚­ãƒ¼ã¨å€¤ã®ãƒšã‚¢ã‹ã‚‰ãªã‚‹ãƒ¬ã‚³ãƒ¼ãƒ‰ç¾¤ã‚’æ ¼ç´ã—ãŸãƒ‡ãƒ¼ã‚¿ãƒ•ァイルã§ã™ã€‚キーã¨å€¤ã¯ä»»æ„ã®é•·ã•ã‚’æŒã¤ä¸€é€£ã®ãƒã‚¤ãƒˆåˆ—ã§ã‚ã‚Šã€æ–‡å­—列ã§ã‚‚ãƒã‚¤ãƒŠãƒªã§ã‚‚扱ã†ã“ã¨ãŒã§ãã¾ã™ã€‚ãƒ†ãƒ¼ãƒ–ãƒ«ã‚„ãƒ‡ãƒ¼ã‚¿åž‹ã®æ¦‚念ã¯ã‚りã¾ã›ã‚“。レコードã¯ãƒãƒƒã‚·ãƒ¥è¡¨ã¾ãŸã¯B+木ã§ç·¨æˆã•れã¾ã™ã€‚

ãƒãƒƒã‚·ãƒ¥è¡¨ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã§ã¯ã€ã‚­ãƒ¼ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹å†…ã§ä¸€æ„ã§ã‚りã€ã‚­ãƒ¼ãŒé‡è¤‡ã™ã‚‹è¤‡æ•°ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’æ ¼ç´ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。ã“ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«å¯¾ã—ã¦ã¯ã€ã‚­ãƒ¼ã¨å€¤ã‚’指定ã—ã¦ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’æ ¼ç´ã—ãŸã‚Šã€ã‚­ãƒ¼ã‚’指定ã—ã¦å¯¾å¿œã™ã‚‹ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’削除ã—ãŸã‚Šã€ã‚­ãƒ¼ã‚’指定ã—ã¦å¯¾å¿œã™ã‚‹ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’検索ã—ãŸã‚Šã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ã¾ãŸã€ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«æ ¼ç´ã—ã¦ã‚ã‚‹å…¨ã¦ã®ã‚­ãƒ¼ã‚’é †ä¸åŒã«ä¸€ã¤ãšã¤å–り出ã™ã“ã¨ã‚‚ã§ãã¾ã™ã€‚ã“ã®ã‚ˆã†ãªæ“作ã¯ã€UNIX標準ã§å®šç¾©ã•れã¦ã„ã‚‹DBMライブラリãŠã‚ˆã³ãã®è¿½å¾“ã§ã‚ã‚‹NDBMã‚„GDBMã«é¡žã™ã‚‹ã‚‚ã®ã§ã™ã€‚QDBMã¯DBMã®ã‚ˆã‚Šè‰¯ã„代替ã¨ã—ã¦åˆ©ç”¨ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚

B+木ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã§ã¯ã€ã‚­ãƒ¼ãŒé‡è¤‡ã™ã‚‹è¤‡æ•°ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’æ ¼ç´ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ã“ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«å¯¾ã—ã¦ã¯ã€ãƒãƒƒã‚·ãƒ¥è¡¨ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã¨åŒæ§˜ã«ã€ã‚­ãƒ¼ã‚’指定ã—ã¦ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’æ ¼ç´ã—ãŸã‚Šå–り出ã—ãŸã‚Šå‰Šé™¤ã—ãŸã‚Šã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚レコードã¯ãƒ¦ãƒ¼ã‚¶ãŒæŒ‡ç¤ºã—ãŸæ¯”較関数ã«åŸºã¥ã„ã¦æ•´åˆ—ã•ã‚Œã¦æ ¼ç´ã•れã¾ã™ã€‚カーソルを用ã„ã¦å„レコードを昇順ã¾ãŸã¯é™é †ã§å‚ç…§ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ã“ã®æ©Ÿæ§‹ã«ã‚ˆã£ã¦ã€æ–‡å­—列ã®å‰æ–¹ä¸€è‡´æ¤œç´¢ã‚„数値ã®ç¯„囲検索ãŒå¯èƒ½ã«ãªã‚Šã¾ã™ã€‚ã¾ãŸã€B+木ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã§ã¯ãƒˆãƒ©ãƒ³ã‚¶ã‚¯ã‚·ãƒ§ãƒ³ãŒåˆ©ç”¨ã§ãã¾ã™ã€‚

QDBMã¯Cã§è¨˜è¿°ã•れã€Cã€C++ã€Javaã€PerlãŠã‚ˆã³Rubyã®APIã¨ã—ã¦æä¾›ã•れã¾ã™ã€‚QDBMã¯POSIX準拠ã®APIã‚’å‚™ãˆã‚‹ãƒ—ラットフォームã§åˆ©ç”¨ã§ãã¾ã™ã€‚QDBMã¯GNU Lesser General Public Licenseã«åŸºã¥ãフリーソフトウェアã§ã™ã€‚


文書

ä»¥ä¸‹ã®æ–‡æ›¸ã‚’ãŠèª­ã¿ãã ã•ã„。ソースパッケージã«ã‚‚åŒã˜ã‚‚ã®ãŒå«ã¾ã‚Œã¦ã„ã¾ã™ã€‚


ダウンロード

以下ã®ãƒ‘ッケージをダウンロードã—ã¦ãã ã•ã„。Linux用ãƒã‚¤ãƒŠãƒªãƒ‘ッケージã¯ã€Cã¨C++ã¨Javaã®APIã¨ã€CGIスクリプトをç´ã‚ã¦ã„ã¾ã™ã€‚Windows用ãƒã‚¤ãƒŠãƒªãƒ‘ッケージã¯ã€Cã¨Javaã®APIã¨ã€CGIスクリプトをç´ã‚ã¦ã„ã¾ã™ã€‚


ãã®ä»–ã®æƒ…å ±

QDBMã¯å¹³æž—幹雄ãŒä½œæˆã—ã¾ã—ãŸã€‚作者ã¨é€£çµ¡ã‚’ã¨ã‚‹ã«ã¯ã€`mikio@fallabs.com' å®›ã«é›»å­ãƒ¡ãƒ¼ãƒ«ã‚’é€ã£ã¦ãã ã•ã„。


qdbm-1.8.78/doc/logo.png0000644000175000017500000002624611426306156013775 0ustar mikiomikio‰PNG  IHDR,nªDÞ”`PLTEóóó÷÷÷ãåæììíÖÙÝÆËÙ¢³Ó„š¿b|£UkŽM[pKMTu‰ª¤É3Hn!2P(O) ,F.:O°¾ÛG#, ¨«±cdfqu|“— =BJ=gÆbKGDˆH pHYs  ­#½utIMEÔ ,-‡Â’D IDATxœÝ]‹r£:“HØ ` ‹ëû¿åö]²'™=ÿÖVíÖqfbǵº[_ßd犲,àQ–Þá³/½Ç7œ§¿éOOŸÃð6¾ ŸùÝ@gã …¥\ß •‡#=ô/¡Qúè9hyz¦Ïá4xð5ìáí5]88žnz!xé ^Ê—å¿…†stÍøDzþ)æ½7~ÛƒÞdNóuq¢pÚøî4ìÑ âïý8ÆÕá´ è"ñ*î/4ö!z6º‚ݹ,K¾Ç«U¿2v.d{¿x¦¡Éh¼ãÒü=õ}†CåÌDƒ`A¢Á—ý†8B®P‘„ÇåÔ ØÂ¬ú¸¶_Àª’mœ?_ë MÙ𸱱Û’üÙåÑ÷¨˜ä‘‚1à “€³â?5²Öë8Ža_8=¾\Ç "¶Ó„.ÏÓã"Ðþ ÂK”(îhpÈ@¥q„8vÞíã²¢_ChïD…™ià5ãs/~7!­25ûHƒOWǸdù _°>PA´K¨6K$™î\ùõQßbgM¦ëâ…Ç”í°c\·nòk×íÎͱ‹+™†£ëû«ÂõÛÚÅÓ›ÇZ3/»+¶Ǭdb„ó8mñ¡+Ê>«³rÅŠïì8н‡WŒpïúØ”i.ŽC¨àeÙÄØOÁù­kÎ>¶ &pÅoÉÏp¡fêö¢Úà:-œ¾ÇîhàLÖHÎXÙÏtE­áƒWÀûóûûCL8ú%ñœÄx|“†Šz»ue»EÖGþ²}9ËùÛ2T{3’ýÙ†í% ||MË&˜&uëñÒýî¹íҔȆmßQÔšæØct¾ÆíhÆFÔí4‚HmËvlã^VS¿5*žŒÃ…å)ögÎýØÇ hŒpt\@¾Ïm?z`ãÚŸpúØTpª=Ç/ïÚ8ŽSËÌ"On. s ¿™Y¥Ø}˜ùóûvC^a¯??[àÖ ¶·t¸Šäx9|]µõÔÝž7ÐDPEÐÔËåÊy\«¬ËPLÖqFqß{Tø ìg ‚×÷k‚´ ëñ„© ˆyoöaÖ #3Úm‹SélZY/ðα5ç³sŽ[»î%¨Ûr=õ¥ãç±_`¿[÷ Z(ô0+€àþt¡op.ÆÊOV‚yi@ šeW@UŠj”̉½Wc?×Óí†páV“5BË>Wžà? &††ðØ/†ÃâÕÑ*€2ØŽ+¢ˆ&dØd 7Mèÿ7-<ÌædžN˜Î8`å@Î~<<ÈÑJnL±/qŠãVº-" Ûzw,ý— Ã|.ãP—>÷—~ìmnëÃ4n3ð§YðŠ0‡;°ÙƒÝ+6x'Ž»ƒ©„Ã7`Ô2ÂúÒƒø¹”:á‡"”Þ®ÉCÖI<&\??¿Ÿˆ¬n;q .XH¬ô‚Ý'rëVžW­Ö±[»Ã=èë ÅMt‘ÏUåCl¶ñ,yöèb ”bóû3³Ã\ƒáýT0¢#€P€Íš–ªðëÒ†e+}»£%¥éƒïAðbGQSŽ­làÚ Ëïp}ïyØ=JX b —Q«†ÆWãŽ\…ðsi9È€¸TÖDæɘ÷æu#¢ÐoF—m–¬…z y•Zo ¸DChÆ Lôá`°ça1r{ÓŒ±iÀŒÓÆs«Îa/ãÂ$+š ÝÆw<ƒß†}ŸFääjÙñyo–qZO@$Û¶4 Î'|2‚ñŸÀðm=(ðþ«}˜—²=Z©8¶g¿ÃÌa3Â:}ŽtvÛ'¸bU.ðY?í›` ßÎqjjurL«å² )Š+âÍÇc¹?EZp‘Óí$jáÄ?¥sÝõ³»‘lÝYˆZgÐüs™¶ ®wOU8Ïæ4ñí§€­î›}£™ÜDõ: Khz «ºB—<Ófòÿ Áž¬j$ß²º³…ÙÞW.ÑHX§húÏ44³a2T”¯9l:@¢}àêÝÈüÜjß‘_ª*²´NŠ¥‰ÜÜÖßµÐh¡¥ûÄqE§4:#tS'ŸÁÑE¼ù3BWn ¶ þLâ€ÿ”† ‰·.4ÊŒU.ð,°Â|±d«9Œ…ð¤Ä“Cä²Iñ¶U-E Aχ ¯'Ýå«S©8°ÜAvžæ4ø—$U ÊŒÐâîLj ŸÎÿ•†û G6ÇñC§›ÏäqHx™aÙ51zg5$ó£7ÇF<)µ:B²ÈcV^±.…h…ɳ„¸Þr¦EFƒÒ/®Ð?¼e$tUÇJÃ¥ÿ —hW¤™KãC]…̺‘©&ZÒƒœ¼4©rlìu5‡Ó?%¢Cçájgù’TWq‘áw~‹ñÚ±nç YìdX4RµÃî%b®¹ÿ-N@ý+4™/Ô¦aHB(èŽ1c¢2R8ElÄlp¦;æÕ8Jί+R.½ZLÉíÉr‡4Bñ É0zéÑqÁç4ÊdÊÿ¤¡ Àï4œÝB?c±Óä™ ”òÉú 'ü<òuW_ªNìk8N²`ë=#vE|t« XMÀ´‹hyàA+ʼi ‹Eî3ÑH§Ë"‰ <ÿBøõOi˜áGlàÞi °»DÃq*dàÀyz‰N¡\^ª´HP~k¸Ô±up~Æà->Ÿ€á;Ä3Ѳ›ózë±âo~´5=üïåE rvß¼l»ȰŒ_É9¢uÝ·ºiêf[«B·hÈqÛ~Ìÿ”†ºãXÔˆY%FãsۧI”Í˯²èZ–Ö¹!v/‰<Ê`aèõŒ]ì#FÈzàtÐcÁôSºvf4àÄ~Yè¨e'ú½ð±ÞV TiHæhbÄÓ>z ª­p‹s-•7P`ê% é%‘&E˜.€Å",;¢…¯‘Ç\ÈkÊŽVAÈLÏ+§äÏ>$q‚ÙGs—K’©_Æ!ª>©J'FØ9ñ%ñ¦¥T1*õtÜjq1)Ÿæ1ŸÔ#çbŠKõwd³Ô‘¿3_J'E9Ì1Ç1M±W•bû¿DuÐ`ÄU¤„ŤÙÛ'0±ÏŒà¦i…¨ô}&„ø¯ÕøªŒâbnhŽJ®‘’åõÌÜäX`*„Œ³h9Ä’.ö³Z!QK7ÍÞ¸:wxp ûŠˆ4I À’%6'­é2¾Áˆ;ÊŽš™y”ÆÚt}ŸÙª¡&8¼é:&l^&†rïN$•´p¢H‰ bŽKojÍʸ”‡H¨S$H Ñp%8Òâä Rjt•ài;®–Jqâûåã{’å«r À‡’ý)ÀdÐÅZ†Æ4ÈZÚD”¸\# ñ(ÚšâÖœ,-tLCAȹ޶¦IrŸ„Ä •r棞UÉ¥³¶žQFµ³yIW¿µ-gY‹„抦ãÞ ì³1Ywà…ÁÈ`T"Cž;…¥F­bdÖÔ3êŠƆFD°'üDk ÜX÷^ô #žê­ƒÕÐ0ÇÀ‹¡ŒãÒ£TqE|N)‹JÑT.EîRïkºÜ¯ ÉÞpßÔQ¨ô&!<)×â8ë%™&öÁYlP^0ïè²ú¾Ö¸ ¯Ì­a›¥]#qyá$¥bé€+甉dÃÖ76;°ñìº;- -޳P¦é3gjI ¿thÐÂô/þöjÌ* E¦"œlŒ·¨´åÃê!-¾ÍŠÑð;íåb<ëÉÕo×ÃíA+è tp"<%Ð!ÍW}z€¨_P­pq¡:3.Èʆî`^–NW¼…ÏÕêps—i\RÃd(Òc$|fúËG\¨ðCîH{_2hÌ‚ih! Gi¦‰Bž\}¬Axá“õsâ•¥ù ýI^B¿¥˜$`v'X”MÁÙ ;šØÉÀׂ½&ŽzìÞ# °)…šZx_%âãF „ûë 7-´&4Žu‰ãIpøw‹ íA&ÁòÑê4¬+ Å RqËãÀÌqÐ*( ã=ma£È²DKy!µoê•Ò?\C;,èÒR®Óh·g›•++IŽd]Êf£7±ãŽ—òél:  #o¸Yмkä*R™Pé½2kóž‡3ÀÁqáTÙ΢ ­^ª&}JXH‚ô¥÷UBÅ8ò¯­NÓPa;õ{Y…38ï¥<žA…7T¯K‰ï$ºJN÷)0}ŠÌ­•¡=Ç[K³Èü»ñ‡®Ã±HMßÔ eɘű×,Û1 lHs“BØB2ѧժ2IšÌõ#–õ¾ºBû9¿€¹&­BÈö£så¼¢Ë÷žQwù4æÏ¸C ±;Õ¹*)x ±ãÊ=meXZ®`ÄÍÓ¨&I°”q8£ÁËe2ñSHq“ãX(ØpÔiñϳ¾é+Áa´ÞH#ÑToZ#:âèx®ÐåÒ4r—OŠ· Ç£ üyÎzºþèe%„ô)-<_”ãH»+p™(†ò |i5ApÜŠ~1 ÉN×ôqPû³Å&榰¤L³–bp)Fi,^•PÕ’Þxÿ5n(´¼ø¡÷Uc¥ S}[ߨÁ×Û¹Ó_èã¢ùÞ3ºòZÈRʉâ:îÅ1r`·8,~Þ6ÒQU’‚ƒ;ÅÉA‡Ø¿Ø Ìºácšó¼VÔw}L—VŸìù¸ šÓ¶ÜñËïÔû*}*\9â±<„ºœž7‰z^±«—5Ðê ¤g´¼`«Óói½®¸vÊ0Ö3Š/»³,Ä´ o˜$•ksÖ9GñlFd‰Ëa€šŸ¤ˆË°ËÐp(ëÄ0¥ï_ÎÈÎT5N‚.‚,=¼¯+ãKï«Ëû9]HA-.þ3TUZÝýÖ3Ú~sqÄØqÐO2ØNÃþ:Û.nNªA^åx»±¹û!ª}‚ŽväM÷y4!CRæ…¬/uÝ¥kLá…Åo‰“¤Ü«Z«2ÝxVžÆAfÑKmµÃl<—.p)¼\¤ž–|&§Í >´$…wWÍñ¤«âøW+ÂÅã8›˜À'ja£4Íî Âr çé©a¢0Ž›_€]Ͷ® ˆ˜iœ=9Ïðš«jËI‚±4JÁ“¥ÞÁG ¡-ÇÌ’åÒéZÀÜPÀ ½Уs™òÕ¾açÊ76í|PM%‰ŸtnÙ‹Ì:Ù?ѼNºí0BÛÄND\† ¦õÈrVôB¢|®ñIp céŠ{·ý)t‡|†Šàºã=u¬¯8•êô?d}µºL˜ MxIØ¢zÌÜÄCøÁZéæJ꿊âúý¼?,G‘*Qæ–/!f¹Eð@RÒaHu´®8,QúäŠ ˜»’²ÎCC¨Ê²Z,Ê:¨h™•^$?ŠW£7ˆFÄ€L²"ÂõÖî”ð@·º'fìîX]¤UHZïJ‘­míØ D-»ql «jÅCæÒ€W˹?©€„[Ǩ§M«FÈõ“}ŠÕ„`Iõ=D‘¨Ÿ1éýßÕü·] íÁ©9KF½×>Ó ¨8º]eú»AŒ‹…v ØP®Ï¢wdã•ç8)ÃÑ8ÈÙIUàd RNðÒ>ÅÇsÒuñrá60ð깎‹«)9ÞG Ÿ—pgUQ¤ qI0q0fIý~À[Ÿb–bž9Žóh ‘,ébb¯¼ªx‹ª.Óc9eek:ŠKºî’ʬjO÷VäRá9q€ [¥”ú8]õ%{Îà5ŸÏØM¼¼ã.GT_Äù‰ YiVÖS˜y÷×a:£VÚqÔãïtgíY£ã«ÑPÊ KB!… •u±.ÄÕÁº¡¤¾›&2ÓÉ4Žm£¿ñ=®{¨AK·±Ï 'Ї1¿Ä#·û4²_p.Ý¿t1ùpi?kn6^v…¢’÷TÑL¹ÎýÜ—º .2Aàx–¨âÄ,¦R­E”j@þý¨æfÌf¹¨:½˜9’qpèŒüKжŽe‡Xf&º,u£9%ü¬àÞW CýÚ_K¾!‡ÚRÉ)TÂ4s‹ ÆOU÷®ãØ a+4WÚìòG_*ݶÁ¥:«³Cfi-ÔœxÈüŒN{ÝÜò–Ùçâ"ÌüH#{`ž·D’Òiàq¸¶Ka™IBÄõ)+ÆŒsU —º?ûkÉhR¾÷s Ð(9@ˆ%ó…úòq0auËigÞ ®d±*xg3_X_ªÈµÛ)ç•Óª#4„ £[+ñ¬% R{v ¹>I‘2´‰¦Ç!qÂeqÌÉO\*†3U£º¹¨sÈ]aÁ¯ýµÜï ¾t¼—~Nx#eïnSÍû]Ì”îRSÅ]òYßXêK¶œø¶*«VŠ—àÈfh¸¾O׬Ú|XkÙç>å«¥X£w’«? nV<Ž9ª Ɖ»ì%æ»N¢÷*q+@ãÇ?Žƒ¡ü/ýœ.õsº’a*Ø©ú“rúíÅš'¦ê—žQ §QqÖÀö}Ä»<­c¤YÔCu‹!õ¥n$u‹ ä >o±v¸OÊÄå,¸¿vm& ®Bc9ñ)gošBgqwWü<î}uA b¼`|1òfîÊùúQO“¤0ȤHŒf fÿ©/•î¶Ž'Ubˆó‹É‡ ÖqRb¹ï{5áKÐ9…Y<ÏÆ|1/¸UÔzl';ÞK²w÷¥º¯x—MÆá7\Æ—>žØ;£åOdŽ÷×NC¤*M2ñF¸…A*y?'–æ £Pò ÀIDAT€Ànqö{°yEŒ"´«ëÕ:þYR19_p9jN.Œ7mPP!µ7Â/® ̆5è«<²á¹Ñt¯7Q݈¡u Yä¤÷\\Š;ê½ZÒ:^z„e.¾¤D’D^{F9M¡Sªºj9Â>—Á—VÂÄY—íiùÖ3z ¸D'«“<_‹ãA«|õƒ‘YÂÂå,s“ò7‘§zm:.dcÕžÂPàa‘¢æ§ÚÖB»©wøuò’Ú%²žQ'=£(03m·rÃß\ ž2iž›†+ÞŠN<öñµD&©Ô‹p0eé •g{œ÷W¼ÈÑ0$–á8…a§‰¾ÜåúrÁ¶×ågÏE4\=‘Tœ^Æ!RÆ ÏI|™Òa²Àa@úÚrWÝ= !n À 2dÉñy •7&Ò/"YwÍË,ÆA•P^ïyÏèŠuý˜,ÍÔ.ñ<ó€à§‘v”.žÉ¢[ä(EiG露@£&}Pi½qç§ÞWêd}éK¥žQükÆ-&Ž—õð²äórH;¦’+)¶Ç¥¥WΜ–ó…ú0ŸÃÀ…ÜϽqAUGÙ†J…ÆÓv¡Å‰^’@Y@`újij¯pÉR£/~§Þg¤a}©Ç™Uy’›ÂKÏgÇÝD ƒñBU¡`œö>éáeµ¾Oéçt×)/¤Áç°frnÉOÄú2_-•ƒøB·{PÿœÀW8Öu¾X‡)’ÆMêÔ<޵2@=£jO1äŸÓafVyu’³ê¯q/D¬ØÙðg_*ÝL+œO)6z´Ç¬€I9ûã8¨1LÂ^”æJýœeÅûuYß¶ôs†ÏÚv¦ÞÚè‹7ŸI_Qüµ/Õ¿õŒÚnÙN´\úšv¶'—¼Ø—mÒ”†ô×’ëAþÚ¯}©²–k©íï“1öqX«»¯ŽÇA ç´•%õs–ˆ¼&ªÓ%ÛEÛŒIó9UܰøXï«n"#½¯JÃ{ ~$ÿÕä‡\ –”"ht_‡­4ŠŒ†ŽC([_jjS3/êŒß"äoãP•L›¿'E•ÜliÏY?g¸R‹:î¹lâþįSýËø£÷5üFC§¾äÊqíKu&q©8U¾MÀ‚#¯½¯©¦r¿ÑàÆŸz_EvÓ>ñ`™gêñª‚õu¥qøÒúRuõÌú9‹÷~NìäDáºóÎ ]XE2ɪ9ÓZ e¿Öûú ¹uŽdëg}©¶Û†æ¸vàϾTmé3&|6¥!ä¥8ÖkbB¶D —φºŸ—'70±`ú5Õ¾ð( e‘hh?g‘ú9ç3dzÜÏ.ß³‡Õ1õ¾× ÷' õ;y²jþ%1RtÀ4ü ÍÄ(à ˆ««ã(ÄÙ ža®·n§Mæêp³jç(îZ*]¾‡‚O›kÊ;ºM•n ËL •v0vÝ)µ"-e¼'3²-Hí²ö¾¾Ððo4ÌÓ`8¨ßÁ†Ë‚½¥TµW¼Ò(Õ|馈þ§qˆ2kœÃ(`nKÇÀ›`7õŠÐ7( é)ð†ä}6µ¢ÉâñÒïm-µÍÂ-°fÏð« À’EdVâìíuå³  å_ièæÄiS$Ù#@Í•ö¥†÷þZ5–JCc…UENC *ª÷çô0'e¸?S÷•È* ÆYŽˆd/^ú9Óµ¥W¤0 ï÷÷¤ãçþCža±=ú'íU=a@¬Æà!,œ€»°‡ÊýFÃk­ÉC¡zh·ûsm>«÷I4ü+’3~TpecÀ¦Ô¼›±òšÈq®Ýy[»8ŠúÖ[hj­¹˜ÄÂÏWQÆÇ`|h—øÇý)̺é£Ã]‡¯@äNÞú ·'‡©ÊvÇôŠ|Ì\©Æq¬ƒlPVѤ½¯?#Mˆ·º>|*ú~œï®ÇÎî‰P‰â]™ÅÔÞ—¾TÜ쵟3m4fýœ2™rëーȧÈh"*#~óEέ'3‹ÕÙ b]׉Ð}~°¡cî‡sJË£4tªV)1^ýØ_‹ÑËÇ\š×–úÁÑm½/K–ßcFQ1†Îƒ§ñڗ꬟³Ô*Jg&3µe°ú"h%Œ*†žôo ‹E¦ (o¤…ʱ¥ì&²¦?ò«¬î¤×_+zë³|Ý/,¿I[ÏüÜ_[hmJ|¿×XÔLñ¹ƒ²T(.~ˆ~¤v/CXo4^úRÍ-PõW˜æ'1ù-ÎÍømOßÔÙIœz°>&Yoʨ/ºg§Ê‰ì{’¨uÆKýÿuÄ冮øhí/xÚ?ÐïCÇï7z@é‘–ƒáíëƒ8 z ì¡Mt°A$«Ù@õðŠ)}Ý!IŽå.ç_û9}2°‡Š\ÍWÚ€“‹ŒM<2ì!jȺؙ nöü¼uï íôÓ§]‚Ÿqå@é)^póúe¹SLc¤„2eCô#‡ð±p¹å¨þ€¿ëQþ[ø—ìžöðŠ ¾Ôú9K­÷Ð~NouÂ@ÄC˜†•ýÊh ù‚ãcŽ%ËÝÛóŸŸÊyøô¸É5iBOàÊÅ2#ÿüò8þ¦û^~q[„øÂduȌ˺À[©‡÷¥/õµŸSÜ-˜O.¬<ˆ—\µ$•¸Y?Öšóf6þù±xšx#žá¢2(1ë‰|dÜ"T‡« o¤'˜—·W~;O ÑQEœÄåã =ó«ó^—÷¥Ö؈“Áædf\ʼ/îÕ'ŽÙëtq®À…øàô¬X÷§þf¥µRþNªö4ž>™I|0rꦜBÑP÷qOÙá‘X%œHŽz.1c<^•²â_Æ¡åØ<¦¼‡÷¥/•!åòùBá§~Îü»LuóÄ?¾Ë”»ˆ×¸_…† L0~õß7î/œ±å‘¤MEì™ýcFÂA†FØ>ÿ²`‰q§ï5{ÐRPÖ¼é CÂe)a“ƒÄ«à»|ÅKoÞ—ªÁ€¶ÄËjÃuçÒ¼³7ë¡’€5Ç]ËÂl¦çÂ÷ sðÆy¤± zÌXÈ=±w¤uªÒÏ™Cs²â¢ƒ žÕï‚É(‹€ô;YdJÕ2?Ã½Ž£Ðq°©ÏúRµBú9mva"³ø/\*ÔÉ»_¨$;/:ΘyŠ(:1£Îñ7Óµ++äåòuùº~«ñ›%´ô yÀ¯®-M mÀ„:E[ÚSñgŸ]ÆQäãȲ)¶4y÷Ÿƒ¯¤5-Þ[è"õsº×~Nëåiúå»LóÞWÇíût‡©ìç è6ÅšèWVÙ0¤.]TîZï2õ×úRF™£(²ïdõêRþãp>§‘—)d9ÅðÌ*´ú¬Ÿ3çìK¼Æ[ËŸ¿/Uœfoý…ìr®Þ O¶ÑpAÙa-¹BÃýL#ï¯-ÞúR³q0â÷qx÷O¿“•#ãE>†Ú_û9EõµVw|vÖ†ÆVP¿ S<$2¢.£¡!^›¬/U7­T²×`øå;Yõ/¯•Ÿÿ³q¨Ÿþ y¦›þý»L­ŸSñ(»:2—¶—×oßej4(Õ«QÒ7ze§Y¯ë„ÒH«ÔŸ4̺ÿíw²º¿Ž£üË8DSh3 *ŠHw†ÔH<º•ú]‚-,ë:½~sU ítøpôn,no4ÜâJƒ"ÂÕ_Æáþ:Žâ/4þ PÅúá%§l4IEND®B`‚qdbm-1.8.78/man/0000755000175000017500000000000011426314252012317 5ustar mikiomikioqdbm-1.8.78/man/cbcodec.10000644000175000017500000001001011426314243013753 0ustar mikiomikio.\" Hey, EMACS: -*- nroff -*- .\" First parameter, NAME, should be all caps .\" Second parameter, SECTION, should be 1-8, maybe w/ subsection .\" other parameters are allowed: see man(7), man(1) .TH CBCODEC 1 "2005-05-23" "Man Page" "Quick Database Manager" .\" Please adjust this date whenever revising the manpage. .\" .\" Some roff macros, for reference: .\" .nh disable hyphenation .\" .hy enable hyphenation .\" .ad l left justify .\" .ad b justify to both left and right margins .\" .nf disable filling .\" .fi enable filling .\" .br insert line break .\" .sp insert n+1 empty lines .\" for manpage-specific macros, see man(7) .SH NAME cbcodec \- popular encoders and decoders .SH SYNOPSIS .B cbcodec url .RI "[-d] [-br] [-rs " base " " target "] [-l] [-e " expr "] [" file "]" .br .B cbcodec base .RI "[-d] [-l] [-c " num "] [-e " expr "] [" file "]" .br .B cbcodec quote .RI "[-d] [-l] [-c " num "] [-e " expr "] [" file "]" .br .B cbcodec mime .RI "[-d] [-hd] [-bd] [-part " num "] [-l] [-ec " code "] [-qp] [-dc] [-e " expr "] [" file "]" .br .B cbcodec csv .RI "[-d] [-t] [-l] [-e " expr "] [-html] [" file "]" .br .B cbcodec xml .RI "[-d] [-p] [-l] [-e " expr "] [-tsv] [" file "]" .br .B cbcodec zlib .RI "[-d] [-gz] [-crc] [" file "]" .br .B cbcodec lzo .RI "[-d] [" file "]" .br .B cbcodec bzip .RI "[-d] [" file "]" .br .B cbcodec iconv .RI "[-ic " code "] [-oc " code "] [-ol " ltype "] [-cn] [-wc] [-um] [" file "]" .br .B cbcodec date .RI "[-wf] [-rf] [-utc] [" str "]" .SH DESCRIPTION This manual page documents briefly the .B cbcodec commands. .PP .\" TeX users may be more comfortable with the \fB\fP and .\" \fI\fP escape sequences to invode bold face and italics, .\" respectively. \fBcbcodec\fP is a tool to use encoding and decoding features provided by Cabin. This command is used in the above format. \fIfile\fP specifies a input file. If it is omitted, the standard input is read. .SH OPTIONS A summary of options is included below. For a complete description, see the file:///usr/share/doc/qdbm-doc/spex.html#cabincli. .TP .B \-d perform decoding (unescaping), not encoding (escaping). .TP .B \-br break up URL into elements. .TP .B \-rs resolve relative URL. .TP .B \-l output the tailing newline. .TP .BI "\-e " expr specify input data directly. .TP .BI "\-c " num limit the number of columns of the encoded data. .TP .B \-hd parse MIME and extract headers in TSV format. .TP .B \-bd parse MIME and extract the body. .TP .BI "\-part " num parse MIME and extract a part. .TP .BI "\-ec " code specify the input encoding, which is UTF-8 by default. .TP .B \-qp use quoted-printable encoding, which is Base64 by default. .TP .B \-dc output the encoding name instead of the result string when decoding. .TP .B \-t parse CSV. Convert the data into TSV. Tab and new-line in a cell are deleted. .TP .B \-html parse CSV. Convert the data into HTML. .TP .B \-p parse XML. Show tags and text sections with dividing headers. .TP .B \-tsv parse XML. Show the result in TSV format. Characters of tabs and new-lines are URL-encoded. .TP .B \-gz use GZIP format. .TP .B \-crc output the CRC32 checksum as hexadecimal and big endian. .TP .BI "\-ic " code specify the input encoding, which is detected automatically by default. .TP .BI "\-oc " code specify the output encoding, which is UTF-8 by default. .TP .BI "\-ol " ltype convert line feed characters, with `unix'(LF), `dos'(CRLF), and `mac'(CR). .TP .B \-cn detect the input encoding and show its name. .TP .B \-wc count the number of characters of the input string of UTF-8. .TP .B \-um output mappings of UCS-2 characters and C strings of UTF-16BE and UTF-8. .TP .B \-wf output in W3CDTF format. .TP .B \-rf output in RFC 1123 format. .TP .B \-utc output the coordinate universal time. .SH SEE ALSO .BR qdbm (3), .BR cabin (3). .SH AUTHOR QDBM was written by Mikio Hirabayashi . .PP This manual page was written by Fumitoshi UKAI , for the Debian project (but may be used by others). qdbm-1.8.78/man/vltsv.10000644000175000017500000000446111426314167013571 0ustar mikiomikio.\" Hey, EMACS: -*- nroff -*- .\" First parameter, NAME, should be all caps .\" Second parameter, SECTION, should be 1-8, maybe w/ subsection .\" other parameters are allowed: see man(7), man(1) .TH VLTSV 1 "2005-05-23" "Man Page" "Quick Database Manager" .\" Please adjust this date whenever revising the manpage. .\" .\" Some roff macros, for reference: .\" .nh disable hyphenation .\" .hy enable hyphenation .\" .ad l left justify .\" .ad b justify to both left and right margins .\" .nf disable filling .\" .fi enable filling .\" .br insert line break .\" .sp insert n+1 empty lines .\" for manpage-specific macros, see man(7) .SH NAME vltsv \- mutual converter between TSV and Villa database .SH SYNOPSIS .B vltsv import .RI "[-bin] " name .br .B vltsv export .RI "[-bin] " name .SH DESCRIPTION This manual page documents briefly the .B vltsv commands. .PP .\" TeX users may be more comfortable with the \fB\fP and .\" \fI\fP escape sequences to invode bold face and italics, .\" respectively. The command \fBvltsv\fP features mutual conversion between a database of Villa and a TSV text. This command is useful when data exchange with another version of QDBM or another DBM, or when data exchange between systems which have different byte orders. This command is used in the above format. \fIname\fP specifies a database name. .PP The subcommand \fBexport\fP reads TSV data from the standard input. The subcommand \fBimport\fP writes TSV data to the standard output. .SH OPTIONS A summary of options is included below. For a complete description, see the file:///usr/share/doc/qdbm-doc/spex.html#villacli. .TP .B \-bin treat records as Base64 format. .SH EXAMPLES For example, to make a database to search `/etc/password' by a user name, perform the following command. .br \fB cat /etc/passwd | tr ':' '\t' | vltsv import casket\fP .br .PP Thus, to retrieve the information of a user `mikio', perform the following command. .br \fB vlmgr get casket mikio\fP .br .SH SEE ALSO .BR qdbm (3), .BR vlmgr (1), .BR villa (3), .BR vlopen (3). .SH AUTHOR QDBM was written by Mikio Hirabayashi . .PP This manual page was written by Fumitoshi UKAI , for the Debian project (but may be used by others). qdbm-1.8.78/man/spextoman0000755000175000017500000000040107644032652014266 0ustar mikiomikio#! /bin/sh # man generator from spex.html egrep '^(
|
|

)' | sed -e 's/@/__at__/g' -e 's//.TP@.B /' -e 's/

/.PP@/' \ -e 's/<[^>]*>//g' -e 's/<//g' -e 's/&/\&/g' -e 's/-/\\-/g' | tr '@' '\n' | sed -e 's/__at__/@/g' qdbm-1.8.78/man/odtest.10000644000175000017500000000272511426314207013711 0ustar mikiomikio.TH ODTEST 1 "2005-06-01" "Man Page" "Quick Database Manager" .SH NAME odtest \- test cases for QDBM Odeum .SH SYNOPSIS .PP .B odtest write .RI "[-tune " ibnum " " idnum " " cbnum " " csiz "] " name " " dnum " " wnum " " pnum .br .B odtest read .I name .br .B odtest combo .I name .br .B odtest wicked .I name dnum .SH DESCRIPTION .PP The command `odtest' is a utility for facility test and performance test. Check a database generated by the command or measure the execution time of the command. This command is used in the following format. `name' specifies a database name. `dnum' specifies the number of the documents. `wnum' specifies the number of words per document. `pnum' specifies the number of patterns of words. .PP .TP .B odtest write [-tune ibnum idnum cbnum csiz] name dnum wnum pnum Store documents with random attributes and random words. .TP .B odtest read name Retrieve all documents of the database above. .TP .B odtest combo name Perform combination test of various operations. .TP .B odtest wicked name dnum Perform updating operations selected at random. .PP Options feature the following. .PP .RS .B -tune ibnum idnum cbnum csiz : set tuning parameters. .RE .PP This command returns 0 on success, another on failure. The environment variable `QDBMDBGFD' specifies the file descriptor to output the history of updating the variable `dpecode'. .SH SEE ALSO .PP .BR qdbm (3), .BR odeum (3) .SH AUTHOR QDBM was written by Mikio Hirabayashi . qdbm-1.8.78/man/odidx.10000644000175000017500000000631211426314214013510 0ustar mikiomikio.\" Hey, EMACS: -*- nroff -*- .\" First parameter, NAME, should be all caps .\" Second parameter, SECTION, should be 1-8, maybe w/ subsection .\" other parameters are allowed: see man(7), man(1) .TH ODIDX 1 "2005-05-23" "Man Page" "Quick Database Manager" .\" Please adjust this date whenever revising the manpage. .\" .\" Some roff macros, for reference: .\" .nh disable hyphenation .\" .hy enable hyphenation .\" .ad l left justify .\" .ad b justify to both left and right margins .\" .nf disable filling .\" .fi enable filling .\" .br insert line break .\" .sp insert n+1 empty lines .\" for manpage-specific macros, see man(7) .SH NAME odidx \- indexer of document files .SH SYNOPSIS .B odidx register .RI "[-l " file "] [-wmax " num "] [-tsuf " sufs "] [-hsuf " sufs "] " name "[" dir "]" .br .B odidx relate .I name .br .B odidx purge .I name .SH DESCRIPTION This manual page documents briefly the .B odidx commands. .PP .\" TeX users may be more comfortable with the \fB\fP and .\" \fI\fP escape sequences to invode bold face and italics, .\" respectively. The command \fBodidx\fP is a utility for indexing files on the local file system. This command is useful for a full-text search system of a Web site. Supported file format are plain text and HTML. Supported character encoding are US-ASCII and ISO-8859-1. The URI of each document is specified with the path of its file. Attributes named as \fItitle\fP and \fIdate\fP are given to each documents. When a document is already existing in the database, it is registered if its last modification time is newer, or it is ignored. Modification times are stored in the sub database `_mtime' in the main database directory. Score information are stored in the sub database `_score' in the main database directory. This command is used in the above format. \fIname\fP specifies a database name. \fIdir\fP specifies a directory name. .SH OPTIONS A summary of options is included below. For a complete description, see the file:///usr/share/doc/qdbm-doc/spex.html#odeumcli. .TP .BI "\-l " file read a file and get list of paths of files to register. If `-' is specified, the standard input is read. .TP .BI "\-wmax " num specify the max number of words to be stored in the document database. .TP .BI "\-tsuf " sufs specify suffixes of plain text files in comma separated format. The default is `-tsuf .txt,.text'. .TP .BI "\-hsuf " sufs specify suffixes of HTML files in comma separated format. The default is `-hsuf .html,.htm'. .SH EXAMPLES For example, to register files which are under `/home/mikio' and whose suffix are `.txt', `.c', or `.h', perform the following command. .br \fB odidx register -tsuf ".txt,.c,.h" -hsuf "" casket /home/mikio\fP .br .PP Thus, to retrieve documents which include `unix' and `posix' and show the top 8 terms, perform the following command. .br \fB odmgr search -max 8 -h casket "unix posix"\fP .br .SH SEE ALSO .BR qdbm (3), .BR odmgr (1), .BR odeum (3), .BR odopen (3). .SH AUTHOR QDBM was written by Mikio Hirabayashi . .PP This manual page was written by Fumitoshi UKAI , for the Debian project (but may be used by others). qdbm-1.8.78/man/cropen.30000644000175000017500000000002110573416637013676 0ustar mikiomikio.so man3/curia.3 qdbm-1.8.78/man/hovel.30000644000175000017500000002544610573416637013547 0ustar mikiomikio.TH HOVEL 3 "2004-04-22" "Man Page" "Quick Database Manager" .SH NAME Hovel \- the GDBM\-compatible API of QDBM .SH SYNOPSIS .PP .B #include .br .B #include .br .B #include .br .B #include .PP .B typedef struct { char *dptr; size_t dsize; } datum; .PP .B extern char *gdbm_version; .PP .B extern gdbm_error gdbm_errno; .PP .B char *gdbm_strerror(gdbm_error gdbmerrno); .PP .B GDBM_FILE gdbm_open(char *name, int block_size, int read_write, int mode, void (*fatal_func)(void)); .PP .B GDBM_FILE gdbm_open2(char *name, int read_write, int mode, int bnum, int dnum, int align); .PP .B void gdbm_close(GDBM_FILE dbf); .PP .B int gdbm_store(GDBM_FILE dbf, datum key, datum content, int flag); .PP .B int gdbm_delete(GDBM_FILE dbf, datum key); .PP .B datum gdbm_fetch(GDBM_FILE dbf, datum key); .PP .B int gdbm_exists(GDBM_FILE dbf, datum key); .PP .B datum gdbm_firstkey(GDBM_FILE dbf); .PP .B datum gdbm_nextkey(GDBM_FILE dbf, datum key); .PP .B void gdbm_sync(GDBM_FILE dbf); .PP .B int gdbm_reorganize(GDBM_FILE dbf); .PP .B int gdbm_fdesc(GDBM_FILE dbf); .PP .B int gdbm_setopt(GDBM_FILE dbf, int option, int *value, int size); .SH DESCRIPTION .PP Hovel is the API which is compatible with GDBM. So, Hovel wraps functions of Depot and Curia as API of GDBM. It is easy to port an application from GDBM to QDBM. In most cases, you should only replace the includings of `gdbm.h' with `hovel.h' and replace the linking option `\-lgdbm' with `\-lqdbm'. Hovel cannot handle database files made by the original GDBM. .PP In order to use Hovel, you should include `hovel.h', `stdlib.h', `sys/types.h' and `sys/stat.h' in the source files. Usually, the following description will be near the beginning of a source file. .PP .RS .B #include .br .B #include .br .B #include .br .B #include .RE .PP An object of `GDBM_FILE' is used as a database handle. A database handle is opened with the function `gdbm_open' and closed with `gdbm_close'. You should not refer directly to any member of a handle. Although Hovel works as a wrapper of Depot and handles a database file usually, if you use the function `gdbm_open2' to open the handle, it is possible to make behavior of a handle as a wrapper of Curia and treat a database directory. .PP Structures of `datum' type is used in order to give and receive data of keys and values with functions of Hovel. .TP .B typedef struct { char *dptr; size_t dsize; } datum; `dptr' specifies the pointer to the region of a key or a value. `dsize' specifies the size of the region. .PP The external variable `gdbm_version' is the string containing the version information. .TP .B extern char *gdbm_version; .PP The external variable `gdbm_errno' is assigned with the last happened error code. Refer to `hovel.h' for details of the error codes. .TP .B extern gdbm_error gdbm_errno; The initial value of this variable is `GDBM_NO_ERROR'. The other values are `GDBM_MALLOC_ERROR', `GDBM_BLOCK_SIZE_ERROR', `GDBM_FILE_OPEN_ERROR', `GDBM_FILE_WRITE_ERROR', `GDBM_FILE_SEEK_ERROR', `GDBM_FILE_READ_ERROR', `GDBM_BAD_MAGIC_NUMBER', `GDBM_EMPTY_DATABASE', `GDBM_CANT_BE_READER', `GDBM_CANT_BE_WRITER', `GDBM_READER_CANT_DELETE', `GDBM_READER_CANT_STORE', `GDBM_READER_CANT_REORGANIZE', `GDBM_UNKNOWN_UPDATE', `GDBM_ITEM_NOT_FOUND', `GDBM_REORGANIZE_FAILED', `GDBM_CANNOT_REPLACE', `GDBM_ILLEGAL_DATA', `GDBM_OPT_ALREADY_SET', and `GDBM_OPT_ILLEGAL'. .PP The function `gdbm_strerror' is used in order to get a message string corresponding to an error code. .TP .B char *gdbm_strerror(gdbm_error gdbmerrno); `gdbmerrno' specifies an error code. The return value is the message string of the error code. The region of the return value is not writable. .PP The function `gdbm_open' is used in order to get a database handle after the fashion of GDBM. .TP .B GDBM_FILE gdbm_open(char *name, int block_size, int read_write, int mode, void (*fatal_func)(void)); `name' specifies the name of a database. `block_size' is ignored. `read_write' specifies the connection mode: `GDBM_READER' as a reader, `GDBM_WRITER', `GDBM_WRCREAT' and `GDBM_NEWDB' as a writer. `GDBM_WRCREAT' makes a database file or directory if it does not exist. `GDBM_NEWDB' makes a new database even if it exists. You can add the following to writer modes by bitwise or: `GDBM_SYNC', `GDBM_NOLOCK', `GDBM_LOCKNB', `GDBM_FAST', and `GDBM_SPARSE'. `GDBM_SYNC' means a database is synchronized after every updating method. `GDBM_NOLOCK' means a database is opened without file locking. `GDBM_LOCKNB' means file locking is performed without blocking. `GDBM_FAST' is ignored. `GDBM_SPARSE' is an original mode of QDBM and makes database a sparse file. `mode' specifies mode of a database file as the one of `open' call does. `fatal_func' is ignored. The return value is the database handle or `NULL' if it is not successful. .PP The function `gdbm_open2' is used in order to get a database handle after the fashion of QDBM. .TP .B GDBM_FILE gdbm_open2(char *name, int read_write, int mode, int bnum, int dnum, int align); `name' specifies the name of a database. `read_write' specifies the connection mode: `GDBM_READER' as a reader, `GDBM_WRITER', `GDBM_WRCREAT' and `GDBM_NEWDB' as a writer. `GDBM_WRCREAT' makes a database file or directory if it does not exist. `GDBM_NEWDB' makes a new database even if it exists. You can add the following to writer modes by bitwise or: `GDBM_SYNC', `GDBM_NOLOCK', `GDBM_LOCKNB', `GDBM_FAST', and `GDBM_SPARSE'. `GDBM_SYNC' means a database is synchronized after every updating method. `GDBM_NOLOCK' means a database is opened without file locking. `GDBM_LOCKNB' means file locking is performed without blocking. `GDBM_FAST' is ignored. `GDBM_SPARSE' is an original mode of QDBM and makes database sparse files. `mode' specifies a mode of a database file or a database directory as the one of `open' or `mkdir' call does. `bnum' specifies the number of elements of each bucket array. If it is not more than 0, the default value is specified. `dnum' specifies the number of division of the database. If it is not more than 0, the returning handle is created as a wrapper of Depot, else, it is as a wrapper of Curia. `align' specifies the basic size of alignment. The return value is the database handle or `NULL' if it is not successful. If the database already exists, whether it is one of Depot or Curia is measured automatically. .PP The function `gdbm_close' is used in order to close a database handle. .TP .B void gdbm_close(GDBM_FILE dbf); `dbf' specifies a database handle. Because the region of the closed handle is released, it becomes impossible to use the handle. .PP The function `gdbm_store' is used in order to store a record. .TP .B int gdbm_store(GDBM_FILE dbf, datum key, datum content, int flag); `dbf' specifies a database handle connected as a writer. `key' specifies a structure of a key. `content' specifies a structure of a value. `flag' specifies behavior when the key overlaps, by the following values: `GDBM_REPLACE', which means the specified value overwrites the existing one, `GDBM_INSERT', which means the existing value is kept. The return value is 0 if it is successful, 1 if it gives up because of overlaps of the key, \-1 if other error occurs. .PP The function `gdbm_delete' is used in order to delete a record. .TP .B int gdbm_delete(GDBM_FILE dbf, datum key); `dbf' specifies a database handle connected as a writer. `key' specifies a structure of a key. The return value is 0 if it is successful, \-1 if some errors occur. .PP The function `gdbm_fetch' is used in order to retrieve a record. .TP .B datum gdbm_fetch(GDBM_FILE dbf, datum key); `dbf' specifies a database handle. `key' specifies a structure of a key. The return value is a structure of the result. If a record corresponds, the member `dptr' of the structure is the pointer to the region of the value. If no record corresponds or some errors occur, `dptr' is `NULL'. Because the region pointed to by `dptr' is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. .PP The function `gdbm_exists' is used in order to check whether a record exists or not. .TP .B int gdbm_exists(GDBM_FILE dbf, datum key); `dbf' specifies a database handle. `key' specifies a structure of a key. The return value is true if a record corresponds and no error occurs, or false, else, it is false. .PP The function `gdbm_firstkey' is used in order to get the first key of a database. .TP .B datum gdbm_firstkey(GDBM_FILE dbf); `dbf' specifies a database handle. The return value is a structure of the result. If a record corresponds, the member `dptr' of the structure is the pointer to the region of the first key. If no record corresponds or some errors occur, `dptr' is `NULL'. Because the region pointed to by `dptr' is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. .PP The function `gdbm_nextkey' is used in order to get the next key of a database. .TP .B datum gdbm_nextkey(GDBM_FILE dbf, datum key); `dbf' specifies a database handle. The return value is a structure of the result. If a record corresponds, the member `dptr' of the structure is the pointer to the region of the next key. If no record corresponds or some errors occur, `dptr' is `NULL'. Because the region pointed to by `dptr' is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. .PP The function `gdbm_sync' is used in order to synchronize updating contents with the file and the device. .TP .B void gdbm_sync(GDBM_FILE dbf); `dbf' specifies a database handle connected as a writer. .PP The function `gdbm_reorganize' is used in order to reorganize a database. .TP .B int gdbm_reorganize(GDBM_FILE dbf); `dbf' specifies a database handle connected as a writer. If successful, the return value is 0, else \-1. .PP The function `gdbm_fdesc' is used in order to get the file descriptor of a database file. .TP .B int gdbm_fdesc(GDBM_FILE dbf); `dbf' specifies a database handle connected as a writer. The return value is the file descriptor of the database file. If the database is a directory the return value is \-1. .PP The function `gdbm_setopt' has no effect. .TP .B int gdbm_setopt(GDBM_FILE dbf, int option, int *value, int size); `dbf' specifies a database handle. `option' is ignored. `size' is ignored. The return value is 0. The function is only for compatibility. .PP If QDBM was built with POSIX thread enabled, the global variable `gdbm_errno' is treated as thread specific data, and functions of Hovel are reentrant. In that case, they are thread\-safe as long as a handle is not accessed by threads at the same time, on the assumption that `errno', `malloc', and so on are thread\-safe. .SH SEE ALSO .PP .BR qdbm (3), .BR depot (3), .BR curia (3), .BR relic (3), .BR cabin (3), .BR villa (3), .BR odeum (3), .BR ndbm (3), .BR gdbm (3) qdbm-1.8.78/man/odopen.30000644000175000017500000000002110573416637013674 0ustar mikiomikio.so man3/odeum.3 qdbm-1.8.78/man/villa.30000644000175000017500000006467510573416637013550 0ustar mikiomikio.TH VILLA 3 "2004-04-22" "Man Page" "Quick Database Manager" .SH NAME Villa \- the advanced API of QDBM .SH SYNOPSIS .PP .B #include .br .B #include .br .B #include .br .B #include .PP .B typedef int(*VLCFUNC)(const char *aptr, int asiz, const char *bptr, int bsiz); .PP .B VILLA *vlopen(const char *name, int omode, VLCFUNC cmp); .PP .B int vlclose(VILLA *villa); .PP .B int vlput(VILLA *villa, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int dmode); .PP .B int vlout(VILLA *villa, const char *kbuf, int ksiz); .PP .B char *vlget(VILLA *villa, const char *kbuf, int ksiz, int *sp); .PP .B int vlvsiz(VILLA *villa, const char *kbuf, int ksiz); .PP .B int vlvnum(VILLA *villa, const char *kbuf, int ksiz); .PP .B int vlputlist(VILLA *villa, const char *kbuf, int ksiz, const CBLIST *vals); .PP .B int vloutlist(VILLA *villa, const char *kbuf, int ksiz); .PP .B CBLIST *vlgetlist(VILLA *villa, const char *kbuf, int ksiz); .PP .B char *vlgetcat(VILLA *villa, const char *kbuf, int ksiz, int *sp); .PP .B int vlcurfirst(VILLA *villa); .PP .B int vlcurlast(VILLA *villa); .PP .B int vlcurprev(VILLA *villa); .PP .B int vlcurnext(VILLA *villa); .PP .B int vlcurjump(VILLA *villa, const char *kbuf, int ksiz, int jmode); .PP .B char *vlcurkey(VILLA *villa, int *sp); .PP .B char *vlcurval(VILLA *villa, int *sp); .PP .B int vlcurput(VILLA *villa, const char *vbuf, int vsiz, int cpmode); .PP .B int vlcurout(VILLA *villa); .PP .B void vlsettuning(VILLA *villa, int lrecmax, int nidxmax, int lcnum, int ncnum); .PP .B int vlsetfbpsiz(VILLA *villa, int size); .PP .B int vlsync(VILLA *villa); .PP .B int vloptimize(VILLA *villa); .PP .B char *vlname(VILLA *villa); .PP .B int vlfsiz(VILLA *villa); .PP .B int vllnum(VILLA *villa); .PP .B int vlnnum(VILLA *villa); .PP .B int vlrnum(VILLA *villa); .PP .B int vlwritable(VILLA *villa); .PP .B int vlfatalerror(VILLA *villa); .PP .B int vlinode(VILLA *villa); .PP .B time_t vlmtime(VILLA *villa); .PP .B int vltranbegin(VILLA *villa); .PP .B int vltrancommit(VILLA *villa); .PP .B int vltranabort(VILLA *villa); .PP .B int vlremove(const char *name); .PP .B int vlrepair(const char *name, VLCFUNC cmp); .PP .B int vlexportdb(VILLA *villa, const char *name); .PP .B int vlimportdb(VILLA *villa, const char *name); .SH DESCRIPTION .PP Villa is the advanced API of QDBM. It provides routines for managing a database file of B+ tree. Each record is stored being sorted in order defined by a user. As for hash databases, retrieving method is provided only as complete accord. However, with Villa, it is possible to retrieve records specified by range. Cursor is used in order to access each record in order. It is possible to store records duplicating keys in a database. Moreover, according to the transaction mechanism, you can commit or abort operations of a database in a lump. .PP Villa is implemented, based on Depot and Cabin. A database file of Villa is actual one of Depot. Although processing speed of retrieving and storing is slower than Depot, the size of a database is smaller. .PP In order to use Villa, you should include `depot.h', `cabin.h', `villa.h' and `stdlib.h' in the source files. Usually, the following description will be near the beginning of a source file. .PP .RS .B #include .br .B #include .br .B #include .br .B #include .RE .PP A pointer to `VILLA' is used as a database handle. It is like that some file I/O routines of `stdio.h' use a pointer to `FILE'. A database handle is opened with the function `vlopen' and closed with `vlclose'. You should not refer directly to any member of the handle. If a fatal error occurs in a database, any access method via the handle except `vlclose' will not work and return error status. Although a process is allowed to use multiple database handles at the same time, handles of the same database file should not be used. Before the cursor is used, it should be initialized by one of `vlcurfirst', `vlcurlast' or `vlcurjump'. Also after storing or deleting a record with functions except for `vlcurput' and `vlcurout', the cursor should be initialized. .PP Villa also assign the external variable `dpecode' with the error code. The function `dperrmsg' is used in order to get the message of the error code. .PP You can define a comparing function to specify the order of records. The function should be the following type. .TP .B typedef int(*VLCFUNC)(const char *aptr, int asiz, const char *bptr, int bsiz); `aptr' specifies the pointer to the region of one key. `asiz' specifies the size of the region of one key. `bptr' specifies the pointer to the region of the other key. `bsiz' specifies the size of the region of the other key. The return value is positive if the former is big, negative if the latter is big, 0 if both are equivalent. .PP The function `vlopen' is used in order to get a database handle. .TP .B VILLA *vlopen(const char *name, int omode, VLCFUNC cmp); `name' specifies the name of a database file. `omode' specifies the connection mode: `VL_OWRITER' as a writer, `VL_OREADER' as a reader. If the mode is `VL_OWRITER', the following may be added by bitwise or: `VL_OCREAT', which means it creates a new database if not exist, `VL_OTRUNC', which means it creates a new database regardless if one exists, `VL_OZCOMP', which means leaves in the database are compressed, `VL_OYCOMP', which means leaves in the database are compressed with LZO, `VL_OXCOMP', which means leaves in the database are compressed with BZIP2. Both of `VL_OREADER' and `VL_OWRITER' can be added to by bitwise or: `VL_ONOLCK', which means it opens a database file without file locking, or `VL_OLCKNB', which means locking is performed without blocking. `cmp' specifies the comparing function: `VL_CMPLEX' comparing keys in lexical order, `VL_CMPINT' comparing keys as objects of `int' in native byte order, `VL_CMPNUM' comparing keys as numbers of big endian, `VL_CMPDEC' comparing keys as decimal strings. Any function based on the declaration of the type `VLCFUNC' can be assigned to the comparing function. The comparing function should be kept same in the life of a database. The return value is the database handle or `NULL' if it is not successful. While connecting as a writer, an exclusive lock is invoked to the database file. While connecting as a reader, a shared lock is invoked to the database file. The thread blocks until the lock is achieved. `VL_OZCOMP', `VL_OYCOMP', and `VL_OXCOMP' are available only if QDBM was built each with ZLIB, LZO, and BZIP2 enabled. If `VL_ONOLCK' is used, the application is responsible for exclusion control. .PP The function `vlclose' is used in order to close a database handle. .TP .B int vlclose(VILLA *villa); `villa' specifies a database handle. If successful, the return value is true, else, it is false. Because the region of a closed handle is released, it becomes impossible to use the handle. Updating a database is assured to be written when the handle is closed. If a writer opens a database but does not close it appropriately, the database will be broken. If the transaction is activated and not committed, it is aborted. .PP The function `vlput' is used in order to store a record. .TP .B int vlput(VILLA *villa, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int dmode); `villa' specifies a database handle connected as a writer. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `vbuf' specifies the pointer to the region of a value. `vsiz' specifies the size of the region of the value. If it is negative, the size is assigned with `strlen(vbuf)'. `dmode' specifies behavior when the key overlaps, by the following values: `VL_DOVER', which means the specified value overwrites the existing one, `VL_DKEEP', which means the existing value is kept, `VL_DCAT', which means the specified value is concatenated at the end of the existing value, `VL_DDUP', which means duplication of keys is allowed and the specified value is added as the last one, `VL_DDUPR', which means duplication of keys is allowed and the specified value is added as the first one. If successful, the return value is true, else, it is false. The cursor becomes unavailable due to updating database. .PP The function `vlout' is used in order to delete a record. .TP .B int vlout(VILLA *villa, const char *kbuf, int ksiz); `villa' specifies a database handle connected as a writer. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. If successful, the return value is true, else, it is false. False is returned when no record corresponds to the specified key. When the key of duplicated records is specified, the first record of the same key is deleted. The cursor becomes unavailable due to updating database. .PP The function `vlget' is used in order to retrieve a record. .TP .B char *vlget(VILLA *villa, const char *kbuf, int ksiz, int *sp); `villa' specifies a database handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the region of the value of the corresponding record, else, it is `NULL'. `NULL' is returned when no record corresponds to the specified key. When the key of duplicated records is specified, the value of the first record of the same key is selected. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. .PP The function `vlvsiz' is used in order to get the size of the value of a record. .TP .B int vlvsiz(VILLA *villa, const char *kbuf, int ksiz); `villa' specifies a database handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. If successful, the return value is the size of the value of the corresponding record, else, it is \-1. If multiple records correspond, the size of the first is returned. .PP The function `vlvnum' is used in order to get the number of records corresponding a key. .TP .B int vlvnum(VILLA *villa, const char *kbuf, int ksiz); `villa' specifies a database handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. The return value is the number of corresponding records. If no record corresponds, 0 is returned. .PP The function `vlputlist' is used in order to store plural records corresponding a key. .TP .B int vlputlist(VILLA *villa, const char *kbuf, int ksiz, const CBLIST *vals); `villa' specifies a database handle connected as a writer. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `vals' specifies a list handle of values. The list should not be empty. If successful, the return value is true, else, it is false. The cursor becomes unavailable due to updating database. .PP The function `vloutlist' is used in order to delete all records corresponding a key. .TP .B int vloutlist(VILLA *villa, const char *kbuf, int ksiz); `villa' specifies a database handle connected as a writer. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. If successful, the return value is true, else, it is false. False is returned when no record corresponds to the specified key. The cursor becomes unavailable due to updating database. .PP The function `vlgetlist' is used in order to retrieve values of all records corresponding a key. .TP .B CBLIST *vlgetlist(VILLA *villa, const char *kbuf, int ksiz); `villa' specifies a database handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. If successful, the return value is a list handle of the values of the corresponding records, else, it is `NULL'. `NULL' is returned when no record corresponds to the specified key. Because the handle of the return value is opened with the function `cblistopen', it should be closed with the function `cblistclose' if it is no longer in use. .PP The function `vlgetcat' is used in order to retrieve concatenated values of all records corresponding a key. .TP .B char *vlgetcat(VILLA *villa, const char *kbuf, int ksiz, int *sp); `villa' specifies a database handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the region of the concatenated values of the corresponding record, else, it is `NULL'. `NULL' is returned when no record corresponds to the specified key. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. .PP The function `vlcurfirst' is used in order to move the cursor to the first record. .TP .B int vlcurfirst(VILLA *villa); `villa' specifies a database handle. If successful, the return value is true, else, it is false. False is returned if there is no record in the database. .PP The function `vlcurlast' is used in order to move the cursor to the last record. .TP .B int vlcurlast(VILLA *villa); `villa' specifies a database handle. If successful, the return value is true, else, it is false. False is returned if there is no record in the database. .PP The function `vlcurprev' is used in order to move the cursor to the previous record. .TP .B int vlcurprev(VILLA *villa); `villa' specifies a database handle. If successful, the return value is true, else, it is false. False is returned if there is no previous record. .PP The function `vlcurnext' is used in order to move the cursor to the next record. .TP .B int vlcurnext(VILLA *villa); `villa' specifies a database handle. If successful, the return value is true, else, it is false. False is returned if there is no next record. .PP The function `vlcurjump' is used in order to move the cursor to a position around a record. .TP .B int vlcurjump(VILLA *villa, const char *kbuf, int ksiz, int jmode); `villa' specifies a database handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `jmode' specifies detail adjustment: `VL_JFORWARD', which means that the cursor is set to the first record of the same key and that the cursor is set to the next substitute if completely matching record does not exist, `VL_JBACKWARD', which means that the cursor is set to the last record of the same key and that the cursor is set to the previous substitute if completely matching record does not exist. If successful, the return value is true, else, it is false. False is returned if there is no record corresponding the condition. .PP The function `vlcurkey' is used in order to get the key of the record where the cursor is. .TP .B char *vlcurkey(VILLA *villa, int *sp); `villa' specifies a database handle. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the region of the key of the corresponding record, else, it is `NULL'. `NULL' is returned when no record corresponds to the cursor. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. .PP The function `vlcurval' is used in order to get the value of the record where the cursor is. .TP .B char *vlcurval(VILLA *villa, int *sp); `villa' specifies a database handle. `sp' specifies the pointer to a variable to which the size of the region of the return value assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the region of the value of the corresponding record, else, it is `NULL'. `NULL' is returned when no record corresponds to the cursor. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. .PP The function `vlcurput' is used in order to insert a record around the cursor. .TP .B int vlcurput(VILLA *villa, const char *vbuf, int vsiz, int cpmode); `villa' specifies a database handle connected as a writer. `vbuf' specifies the pointer to the region of a value. `vsiz' specifies the size of the region of the value. If it is negative, the size is assigned with `strlen(vbuf)'. `cpmode' specifies detail adjustment: `VL_CPCURRENT', which means that the value of the current record is overwritten, `VL_CPBEFORE', which means that a new record is inserted before the current record, `VL_CPAFTER', which means that a new record is inserted after the current record. If successful, the return value is true, else, it is false. False is returned when no record corresponds to the cursor. After insertion, the cursor is moved to the inserted record. .PP The function `vlcurout' is used in order to delete the record where the cursor is. .TP .B int vlcurout(VILLA *villa); `villa' specifies a database handle connected as a writer. If successful, the return value is true, else, it is false. False is returned when no record corresponds to the cursor. After deletion, the cursor is moved to the next record if possible. .PP The function `vlsettuning' is used in order to set the tuning parameters for performance. .TP .B void vlsettuning(VILLA *villa, int lrecmax, int nidxmax, int lcnum, int ncnum); `villa' specifies a database handle. `lrecmax' specifies the max number of records in a leaf node of B+ tree. If it is not more than 0, the default value is specified. `nidxmax' specifies the max number of indexes in a non\-leaf node of B+ tree. If it is not more than 0, the default value is specified. `lcnum' specifies the max number of caching leaf nodes. If it is not more than 0, the default value is specified. `ncnum' specifies the max number of caching non\-leaf nodes. If it is not more than 0, the default value is specified. The default setting is equivalent to `vlsettuning(49, 192, 1024, 512)'. Because tuning parameters are not saved in a database, you should specify them every opening a database. .PP The function `vlsetfbpsiz' is used in order to set the size of the free block pool of a database handle. .TP .B int vlsetfbpsiz(VILLA *villa, int size); `villa' specifies a database handle connected as a writer. `size' specifies the size of the free block pool of a database. If successful, the return value is true, else, it is false. The default size of the free block pool is 256. If the size is greater, the space efficiency of overwriting values is improved with the time efficiency sacrificed. .PP The function `vlsync' is used in order to synchronize updating contents with the file and the device. .TP .B int vlsync(VILLA *villa); `villa' specifies a database handle connected as a writer. If successful, the return value is true, else, it is false. This function is useful when another process uses the connected database file. This function should not be used while the transaction is activated. .PP The function `vloptimize' is used in order to optimize a database. .TP .B int vloptimize(VILLA *villa); `villa' specifies a database handle connected as a writer. If successful, the return value is true, else, it is false. In an alternating succession of deleting and storing with overwrite or concatenate, dispensable regions accumulate. This function is useful to do away with them. This function should not be used while the transaction is activated. .PP The function `vlname' is used in order to get the name of a database. .TP .B char *vlname(VILLA *villa); `villa' specifies a database handle. If successful, the return value is the pointer to the region of the name of the database, else, it is `NULL'. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. .PP The function `vlfsiz' is used in order to get the size of a database file. .TP .B int vlfsiz(VILLA *villa); `villa' specifies a database handle. If successful, the return value is the size of the database file, else, it is \-1. Because of the I/O buffer, the return value may be less than the hard size. .PP The function `vllnum' is used in order to get the number of the leaf nodes of B+ tree. .TP .B int vllnum(VILLA *villa); `villa' specifies a database handle. If successful, the return value is the number of the leaf nodes, else, it is \-1. .PP The function `vlnnum' is used in order to get the number of the non\-leaf nodes of B+ tree. .TP .B int vlnnum(VILLA *villa); `villa' specifies a database handle. If successful, the return value is the number of the non\-leaf nodes, else, it is \-1. .PP The function `vlrnum' is used in order to get the number of the records stored in a database. .TP .B int vlrnum(VILLA *villa); `villa' specifies a database handle. If successful, the return value is the number of the records stored in the database, else, it is \-1. .PP The function `vlwritable' is used in order to check whether a database handle is a writer or not. .TP .B int vlwritable(VILLA *villa); `villa' specifies a database handle. The return value is true if the handle is a writer, false if not. .PP The function `vlfatalerror' is used in order to check whether a database has a fatal error or not. .TP .B int vlfatalerror(VILLA *villa); `villa' specifies a database handle. The return value is true if the database has a fatal error, false if not. .PP The function `vlinode' is used in order to get the inode number of a database file. .TP .B int vlinode(VILLA *villa); `villa' specifies a database handle. The return value is the inode number of the database file. .PP The function `vlmtime' is used in order to get the last modified time of a database. .TP .B time_t vlmtime(VILLA *villa); `villa' specifies a database handle. The return value is the last modified time of the database. .PP The function `vltranbegin' is used in order to begin the transaction. .TP .B int vltranbegin(VILLA *villa); `villa' specifies a database handle connected as a writer. If successful, the return value is true, else, it is false. Because this function does not perform mutual exclusion control in multi\-thread, the application is responsible for it. Only one transaction can be activated with a database handle at the same time. .PP The function `vltrancommit' is used in order to commit the transaction. .TP .B int vltrancommit(VILLA *villa); `villa' specifies a database handle connected as a writer. If successful, the return value is true, else, it is false. Updating a database in the transaction is fixed when it is committed successfully. .PP The function `vltranabort' is used in order to abort the transaction. .TP .B int vltranabort(VILLA *villa); `villa' specifies a database handle connected as a writer. If successful, the return value is true, else, it is false. Updating a database in the transaction is discarded when it is aborted. The state of the database is rollbacked to before transaction. .PP The function `vlremove' is used in order to remove a database file. .TP .B int vlremove(const char *name); `name' specifies the name of a database file. If successful, the return value is true, else, it is false. .PP The function `vlrepair' is used in order to repair a broken database file. .TP .B int vlrepair(const char *name, VLCFUNC cmp); `name' specifies the name of a database file. `cmp' specifies the comparing function of the database file. If successful, the return value is true, else, it is false. There is no guarantee that all records in a repaired database file correspond to the original or expected state. .PP The function `vlexportdb' is used in order to dump all records as endian independent data. .TP .B int vlexportdb(VILLA *villa, const char *name); `villa' specifies a database handle. `name' specifies the name of an output file. If successful, the return value is true, else, it is false. .PP The function `vlimportdb' is used in order to load all records from endian independent data. .TP .B int vlimportdb(VILLA *villa, const char *name); `villa' specifies a database handle connected as a writer. The database of the handle must be empty. `name' specifies the name of an input file. If successful, the return value is true, else, it is false. .PP If QDBM was built with POSIX thread enabled, the global variable `dpecode' is treated as thread specific data, and functions of Villa are reentrant. In that case, they are thread\-safe as long as a handle is not accessed by threads at the same time, on the assumption that `errno', `malloc', and so on are thread\-safe. .PP Vista is the extended API of Villa. To compensate for the defect that Villa can not handle a file whose size is more than 2GB, Vista does not use Depot but Curia for handling its internal database. While Vista provides data structure and operations of B+ tree as with Villa, its database is realized as a directory. .PP In order to use Vista, you should include `vista.h' instead of `villa.h'. Because Vista is implemented by overriding symbols of Villa, it can be used as with Villa. That is, Signatures of Villa and Vista is all the same. However, as its adverse effect, modules using Vista can not use Depot nor Villa. .SH SEE ALSO .PP .BR qdbm (3), .BR depot (3), .BR curia (3), .BR relic (3), .BR hovel (3), .BR cabin (3), .BR odeum (3), .BR ndbm (3), .BR gdbm (3) qdbm-1.8.78/man/relic.30000644000175000017500000001564610573416637013531 0ustar mikiomikio.TH RELIC 3 "2004-04-22" "Man Page" "Quick Database Manager" .SH NAME Relic \- the NDBM\-compatible API of QDBM .SH SYNOPSIS .PP .B #include .br .B #include .br .B #include .br .B #include .br .B #include .PP .B typedef struct { void *dptr; size_t dsize; } datum; .PP .B DBM *dbm_open(char *name, int flags, int mode); .PP .B void dbm_close(DBM *db); .PP .B int dbm_store(DBM *db, datum key, datum content, int flags); .PP .B int dbm_delete(DBM *db, datum key); .PP .B datum dbm_fetch(DBM *db, datum key); .PP .B datum dbm_firstkey(DBM *db); .PP .B datum dbm_nextkey(DBM *db); .PP .B int dbm_error(DBM *db); .PP .B int dbm_clearerr(DBM *db); .PP .B int dbm_rdonly(DBM *db); .PP .B int dbm_dirfno(DBM *db); .PP .B int dbm_pagfno(DBM *db); .SH DESCRIPTION .PP Relic is the API which is compatible with NDBM. So, Relic wraps functions of Depot as API of NDBM. It is easy to port an application from NDBM to QDBM. In most cases, you should only replace the includings of `ndbm.h' with `relic.h' and replace the linking option `\-lndbm' with `\-lqdbm'. .PP The original NDBM treats a database as a pair of files. One, `a directory file', has a name with suffix `.dir' and stores a bit map of keys. The other, `a data file', has a name with suffix `.pag' and stores entities of each records. Relic creates the directory file as a mere dummy file and creates the data file as a database. Relic has no restriction about the size of each record. Relic cannot handle database files made by the original NDBM. .PP In order to use Relic, you should include `relic.h', `stdlib.h', `sys/types.h', `sys/stat.h' and `fcntl.h' in the source files. Usually, the following description will be near the beginning of a source file. .PP .RS .B #include .br .B #include .br .B #include .br .B #include .br .B #include .RE .PP A pointer to `DBM' is used as a database handle. A database handle is opened with the function `dbm_open' and closed with `dbm_close'. You should not refer directly to any member of a handle. .PP Structures of `datum' type is used in order to give and receive data of keys and values with functions of Relic. .TP .B typedef struct { void *dptr; size_t dsize; } datum; `dptr' specifies the pointer to the region of a key or a value. `dsize' specifies the size of the region. .PP The function `dbm_open' is used in order to get a database handle. .TP .B DBM *dbm_open(char *name, int flags, int mode); `name' specifies the name of a database. The file names are concatenated with suffixes. `flags' is the same as one of `open' call, although `O_WRONLY' is treated as `O_RDWR' and additional flags except for `O_CREAT' and `O_TRUNC' have no effect. `mode' specifies the mode of the database file as one of `open' call does. The return value is the database handle or `NULL' if it is not successful. .PP The function `dbm_close' is used in order to close a database handle. .TP .B void dbm_close(DBM *db); `db' specifies a database handle. Because the region of the closed handle is released, it becomes impossible to use the handle. .PP The function `dbm_store' is used in order to store a record. .TP .B int dbm_store(DBM *db, datum key, datum content, int flags); `db' specifies a database handle. `key' specifies a structure of a key. `content' specifies a structure of a value. `flags' specifies behavior when the key overlaps, by the following values: `DBM_REPLACE', which means the specified value overwrites the existing one, `DBM_INSERT', which means the existing value is kept. The return value is 0 if it is successful, 1 if it gives up because of overlaps of the key, \-1 if other error occurs. .PP The function `dbm_delete' is used in order to delete a record. .TP .B int dbm_delete(DBM *db, datum key); `db' specifies a database handle. `key' specifies a structure of a key. The return value is 0 if it is successful, \-1 if some errors occur. .PP The function `dbm_fetch' is used in order to retrieve a record. .TP .B datum dbm_fetch(DBM *db, datum key); `db' specifies a database handle. `key' specifies a structure of a key. The return value is a structure of the result. If a record corresponds, the member `dptr' of the structure is the pointer to the region of the value. If no record corresponds or some errors occur, `dptr' is `NULL'. `dptr' points to the region related with the handle. The region is available until the next time of calling this function with the same handle. .PP The function `dbm_firstkey' is used in order to get the first key of a database. .TP .B datum dbm_firstkey(DBM *db); `db' specifies a database handle. The return value is a structure of the result. If a record corresponds, the member `dptr' of the structure is the pointer to the region of the first key. If no record corresponds or some errors occur, `dptr' is `NULL'. `dptr' points to the region related with the handle. The region is available until the next time of calling this function or the function `dbm_nextkey' with the same handle. .PP The function `dbm_nextkey' is used in order to get the next key of a database. .TP .B datum dbm_nextkey(DBM *db); `db' specifies a database handle. The return value is a structure of the result. If a record corresponds, the member `dptr' of the structure is the pointer to the region of the next key. If no record corresponds or some errors occur, `dptr' is `NULL'. `dptr' points to the region related with the handle. The region is available until the next time of calling this function or the function `dbm_firstkey' with the same handle. .PP The function `dbm_error' is used in order to check whether a database has a fatal error or not. .TP .B int dbm_error(DBM *db); `db' specifies a database handle. The return value is true if the database has a fatal error, false if not. .PP The function `dbm_clearerr' has no effect. .TP .B int dbm_clearerr(DBM *db); `db' specifies a database handle. The return value is 0. The function is only for compatibility. .PP The function `dbm_rdonly' is used in order to check whether a handle is read\-only or not. .TP .B int dbm_rdonly(DBM *db); `db' specifies a database handle. The return value is true if the handle is read\-only, or false if not read\-only. .PP The function `dbm_dirfno' is used in order to get the file descriptor of a directory file. .TP .B int dbm_dirfno(DBM *db); `db' specifies a database handle. The return value is the file descriptor of the directory file. .PP The function `dbm_pagfno' is used in order to get the file descriptor of a data file. .TP .B int dbm_pagfno(DBM *db); `db' specifies a database handle. The return value is the file descriptor of the data file. .PP Functions of Relic are thread\-safe as long as a handle is not accessed by threads at the same time, on the assumption that `errno', `malloc', and so on are thread\-safe. .SH SEE ALSO .PP .BR qdbm (3), .BR depot (3), .BR curia (3), .BR hovel (3), .BR cabin (3), .BR villa (3), .BR odeum (3), .BR ndbm (3), .BR gdbm (3) qdbm-1.8.78/man/qdbm.30000644000175000017500000003147511426314164013342 0ustar mikiomikio.TH QDBM 3 "2004-04-22" "Man Page" "Quick Database Manager" .SH NAME QDBM \- quick database manager .SH OVERVIEW .PP QDBM is a library of routines for managing a database. The database is a simple data file containing records, each is a pair of a key and a value. Every key and value is serial bytes with variable length. Both binary data and character string can be used as a key and a value. There is neither concept of data tables nor data types. Records are organized in hash table or B+ tree. .PP As for database of hash table, each key must be unique within a database, so it is impossible to store two or more records with a key overlaps. The following access methods are provided to the database: storing a record with a key and a value, deleting a record by a key, retrieving a record by a key. Moreover, traversal access to every key are provided, although the order is arbitrary. These access methods are similar to ones of DBM (or its followers: NDBM and GDBM) library defined in the UNIX standard. QDBM is an alternative for DBM because of its higher performance. .PP As for database of B+ tree, records whose keys are duplicated can be stored. Access methods of storing, deleting, and retrieving are provided as with the database of hash table. Records are stored in order by a comparing function assigned by a user. It is possible to access each record with the cursor in ascending or descending order. According to this mechanism, forward matching search for strings and range search for integers are realized. Moreover, transaction is available in database of B+ tree. .SH EFFECTIVE IMPLEMENTATION OF HASH DATABASE .PP QDBM is developed referring to GDBM for the purpose of the following three points: higher processing speed, smaller size of a database file, and simpler API. They have been achieved. Moreover, the following three restrictions of traditional DBM: a process can handle only one database, the size of a key and a value is bounded, a database file is sparse, are cleared. .PP QDBM uses hash algorithm to retrieve records. If a bucket array has sufficient number of elements, the time complexity of retrieval is `O(1)'. That is, time required for retrieving a record is constant, regardless of the scale of a database. It is also the same about storing and deleting. Collision of hash values is managed by separate chaining. Data structure of the chains is binary search tree. Even if a bucket array has unusually scarce elements, the time complexity of retrieval is `O(log n)'. .PP QDBM attains improvement in retrieval by loading RAM with the whole of a bucket array. If a bucket array is on RAM, it is possible to access a region of a target record by about one path of file operations. A bucket array saved in a file is not read into RAM with the `read' call but directly mapped to RAM with the `mmap' call. Therefore, preparation time on connecting to a database is very short, and two or more processes can share the same memory map. .PP If the number of elements of a bucket array is about half of records stored within a database, although it depends on characteristic of the input, the probability of collision of hash values is about 56.7% (36.8% if the same, 21.3% if twice, 11.5% if four times, 6.0% if eight times). In such case, it is possible to retrieve a record by two or less paths of file operations. If it is made into a performance index, in order to handle a database containing one million of records, a bucket array with half a million of elements is needed. The size of each element is 4 bytes. That is, if 2M bytes of RAM is available, a database containing one million records can be handled. .PP QDBM provides two modes to connect to a database: `reader' and `writer'. A reader can perform retrieving but neither storing nor deleting. A writer can perform all access methods. Exclusion control between processes is performed when connecting to a database by file locking. While a writer is connected to a database, neither readers nor writers can be connected. While a reader is connected to a database, other readers can be connect, but writers can not. According to this mechanism, data consistency is guaranteed with simultaneous connections in multitasking environment. .PP Traditional DBM provides two modes of the storing operations: `insert' and `replace'. In the case a key overlaps an existing record, the insert mode keeps the existing value, while the replace mode transposes it to the specified value. In addition to the two modes, QDBM provides `concatenate' mode. In the mode, the specified value is concatenated at the end of the existing value and stored. This feature is useful when adding a element to a value as an array. Moreover, although DBM has a method to fetch out a value from a database only by reading the whole of a region of a record, QDBM has a method to fetch out a part of a region of a value. When a value is treated as an array, this feature is also useful. .PP Generally speaking, while succession of updating, fragmentation of available regions occurs, and the size of a database grows rapidly. QDBM deal with this problem by coalescence of dispensable regions and reuse of them, and featuring of optimization of a database. When overwriting a record with a value whose size is greater than the existing one, it is necessary to remove the region to another position of the file. Because the time complexity of the operation depends on the size of the region of a record, extending values successively is inefficient. However, QDBM deal with this problem by alignment. If increment can be put in padding, it is not necessary to remove the region. .PP As for many file systems, it is impossible to handle a file whose size is more than 2GB. To deal with this problem, QDBM provides a directory database containing multiple database files. Due to this feature, it is possible to handle a database whose total size is up to 1TB in theory. Moreover, because database files can be deployed on multiple disks, the speed of updating operations can be improved as with RAID\-0 (striping). It is also possible for the database files to deploy on multiple file servers using NFS and so on. .SH USEFUL IMPLEMENTATION OF B+ TREE DATABASE .PP Although B+ tree database is slower than hash database, it features ordering access to each record. The order can be assigned by users. Records of B+ tree are sorted and arranged in logical pages. Sparse index organized in B tree that is multiway balanced tree are maintained for each page. Thus, the time complexity of retrieval and so on is `O(log n)'. Cursor is provided to access each record in order. The cursor can jump to a position specified by a key and can step forward or backward from the current position. Because each page is arranged as double linked list, the time complexity of stepping cursor is `O(1)'. .PP B+ tree database is implemented, based on above hash database. Because each page of B+ tree is stored as each record of hash database, B+ tree database inherits efficiency of storage management of hash database. Because the header of each record is smaller and alignment of each page is calculated statistically, in most cases, the size of database file is cut by half compared to one of hash database. Although operation of many pages are required to update B+ tree, QDBM expedites the process by caching pages and reducing file operations. In most cases, because whole of the sparse index is cached on memory, it is possible to retrieve a record by one or less path of file operations. .PP B+ tree database features transaction mechanism. It is possible to commit a series of operations between the beginning and the end of the transaction in a lump, or to abort the transaction and perform rollback to the state before the transaction. Even if the process of an application is crushed while the transaction, the database file is not broken. .PP In case that QDBM is built with ZLIB, LZO, or BZIP2 enabled, a lossless data\-compression library, the content of each page of B+ tree is compressed and stored in a file. Because each record in a page has similar patterns, high efficiency of compression is expected due to the Lempel-Ziv algorithm and the like. In case handling text data, the size of a database is reduced to about 25%. If the scale of a database is large and disk I/O is the bottleneck, featuring compression makes the processing speed improved to a large extent. .SH SIMPLE BUT VARIOUS INTERFACES .PP QDBM provides very simple APIs. You can perform database I/O as usual file I/O with `FILE' pointer defined in ANSI C. In the basic API of QDBM, entity of a database is recorded as one file. In the extended API, entity of a database is recorded as several files in one directory. Because the two APIs are very similar with each other, porting an application from one to the other is easy. .PP APIs which are compatible with NDBM and GDBM are also provided. As there are a lot of applications using NDBM or GDBM, it is easy to port them onto QDBM. In most cases, it is completed only by replacement of header including (#include) and re\-compiling. However, QDBM can not handle database files made by the original NDBM or GDBM. .PP In order to handle records on memory easily, the utility API is provided. It implements memory allocating functions, sorting functions, extensible datum, array list, hash map, and so on. Using them, you can handle records in C language cheaply as in such script languages as Perl or Ruby. .PP B+ tree database is used with the advanced API. The advanced API is implemented using the basic API and the utility API. Because the advanced API is also similar to the basic API and the extended API, it is easy to learn how to use it. .PP In order to handle an inverted index which is used by full\-text search systems, the inverted API is provided. If it is easy to handle an inverted index of documents, an application can focus on text processing and natural language processing. Because this API does not depend on character codes nor languages, it is possible to implement a full\-text search system which can respond to various requests from users. .PP Along with APIs for C, QDBM provides APIs for C++, Java, Perl, and Ruby. APIs for C are composed of seven kinds: the basic API, the extended API, the NDBM\-compatible API, the GDBM\-compatible API, the utility API, the advanced API, and the inverted API. Command line interfaces corresponding to each API are also provided. They are useful for prototyping, testing, debugging, and so on. The C++ API encapsulates database handling functions of the basic API, the extended API, and the advanced API with class mechanism of C++. The Java API has native methods calling the basic API, the extended API, and the advanced API with Java Native Interface. The Perl API has methods calling the basic API, the extended API, and the advanced API with XS language. The Ruby API has method calling the basic API, the extended API, and the advanced API as modules of Ruby. Moreover, CGI scripts for administration of databases and full-text search are provided. .SH WIDE PORTABILITY .PP QDBM is implemented being based on syntax of ANSI C (C89) and using only APIs defined in ANSI C or POSIX. Thus, QDBM works on most UNIX and its compatible OSs. As for C API, checking operations have been done at least on Linux 2.2, Linux 2.4, FreeBSD 4.8, FreeBSD 5.0, SunOS 5.7, SunOS 5.8, SunOS 5.9, HP\-UX 11.00, Cygwin 1.3.10, Mac OS X 10.2, and RISC OS 5.03. Although a database file created by QDBM depends on byte order of the processor, to do with it, utilities to dump data in format which is independent to byte orders are provided. .SH BUILDING .PP For building a program using QDBM, the program should be linked with a library file `libqdbm.a' or `libqdbm.so'. For example, the following command is executed to build `sample' from `sample.c'. .PP .RS .B gcc \-I/usr/local/include \-o sample sample.c \-L/usr/local/lib \-lqdbm .RE .SH AUTHOR .PP QDBM is written by Mikio Hirabayashi. You can contact the author by e\-mail to . Any suggestion or bug report is welcome to the author. .SH COPYRIGHT .PP Copyright(c) 2000\-2003 Mikio Hirabayashi .PP QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or any later version. .PP QDBM is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. .PP You should have received a copy of the GNU Lesser General Public License along with QDBM; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111\-1307 USA. .SH SEE ALSO .PP .BR depot (3), .BR curia (3), .BR relic (3), .BR hovel (3), .BR cabin (3), .BR villa (3), .BR odeum (3), .BR ndbm (3), .BR gdbm (3) qdbm-1.8.78/man/vltest.10000644000175000017500000000445111426314171013726 0ustar mikiomikio.TH VLTEST 1 "2005-06-01" "Man Page" "Quick Database Manager" .SH NAME vltest \- test cases for QDBM Villa .SH SYNOPSIS .PP .B vltest write .RI "[-int] [-cz|-cy|-cx] [-tune " lrecmax " " nidxmax " " lcnum " " ncnum "] [-fbp " num "] " name " " rnum .br .B vltest read .RI "[-int] " name .br .B vltest rdup .RI "[-int] [-cz|-cy|-cx] [-cc] [-tune " lrecmax " " nidxmax " " lcnum " " ncnum "] [-fbp " num "] " name " " rnum " " pnum .br .B vltest combo .RI "[-cz|-cy|-cx] " name .br .B vltest wicked .RI "[-c] [-cz|-cy|-cx] " name " " rnum .SH DESCRIPTION .PP The command `vltest' is a utility for facility test and performance test. Check a database generated by the command or measure the execution time of the command. This command is used in the following format. `name' specifies a database name. `rnum' specifies the number of the records. .PP .TP .B vltest write [-int] [-cz|-cy|-cx] [-tune lrecmax nidxmax lcnum ncnum] [-fbp num] name rnum Store records with keys of 8 bytes. They change as `00000001', `00000002'... .TP .B vltest read [-int] [-vc] name Retrieve all records of the database above. .TP .B vltest rdup [-int] [-cz|-cy|-cx] [-cc] [-tune lrecmax nidxmax lcnum ncnum] [-fbp num] name rnum pnum Store records with partway duplicated keys using duplicate mode. .TP .B vltest combo [-cz|-cy|-cx] name Perform combination test of various operations. .TP .B vltest wicked [-c] [-cz|-cy|-cx] name rnum Perform updating operations selected at random. .PP Options feature the following. .PP .RS .B -int : treat keys and values as objects of `int', and use comparing function `VL_CMPINT'. .br .B -cz : compress leaves in the database with ZLIB. .br .B -cy : compress leaves in the database with LZO. .br .B -cx : compress leaves in the database with BZIP2. .br .B -vc : refer to volatile cache. .br .B -cc : select `VL_DCAT' or `VL_DDUP' at random. .br .B -tune lrecmax nidxmax lcnum ncnum : set tuning parameters. .br .B -fbp num : set the size of the free block pool. .br .B -c : perform comparison test with map of Cabin. .RE .PP This command returns 0 on success, another on failure. The environment variable `QDBMDBGFD' specifies the file descriptor to output the history of updating the variable `dpecode'. .SH SEE ALSO .PP .BR qdbm (3), .BR villa (3) .SH AUTHOR QDBM was written by Mikio Hirabayashi . qdbm-1.8.78/man/qmttest.10000644000175000017500000000103311426314204014074 0ustar mikiomikio.TH QMTTEST 1 "2006-08-10" "Man Page" "Quick Database Manager" .SH NAME qmttest \- test cases for thread-safety .SH SYNOPSIS .B qmttest .I name rnum tnum .SH DESCRIPTION This manual page documents briefly the .B qmttest commands. .PP The command \fBqmttest\fP is utility for facility test of thread-safety. \fIname\fP specifies the prefix of databases. \fIrnum\fP specifies the number of records. \fItnum\fP specifies the number of threads. .SH SEE ALSO .BR qdbm (3) .SH AUTHOR QDBM was written by Mikio Hirabayashi . qdbm-1.8.78/man/dptsv.10000644000175000017500000000476311426314223013551 0ustar mikiomikio.\" Hey, EMACS: -*- nroff -*- .\" First parameter, NAME, should be all caps .\" Second parameter, SECTION, should be 1-8, maybe w/ subsection .\" other parameters are allowed: see man(7), man(1) .TH DPTSV 1 "2005-05-23" "Man Page" "Quick Database Manager" .\" Please adjust this date whenever revising the manpage. .\" .\" Some roff macros, for reference: .\" .nh disable hyphenation .\" .hy enable hyphenation .\" .ad l left justify .\" .ad b justify to both left and right margins .\" .nf disable filling .\" .fi enable filling .\" .br insert line break .\" .sp insert n+1 empty lines .\" for manpage-specific macros, see man(7) .SH NAME dptsv \- mutual converter between TSV and QDBM Depot database .SH SYNOPSIS .B dptsv import .RI "[-bnum " num "] [-bin] " name .br .B dptsv export .RI "[-bin] " name .SH DESCRIPTION This manual page documents briefly the .B dptsv commands. .PP .\" TeX users may be more comfortable with the \fB\fP and .\" \fI\fP escape sequences to invode bold face and italics, .\" respectively. The command \fIdptsv\fP features mutual conversion between a database of Depot and a TSV text. This command is useful when data exchange with another version of QDBM or another DBM, or when data exchange between systems which have different byte orders. This command is used in the above format. \fIname\fP specifies a database name. .PP The subcommand \fBexport\fP reads TSV data from the standard input. If a key overlaps, the latter is adopted. \fB-bnum\fP specifies the number of the elements of the bucket array. The subcommand \fBimport\fP writes TSV data to the standard output. .SH OPTIONS A summary of options is included below. For a complete description, see the file:///usr/share/doc/qdbm-doc/spex.html#depotcli. .TP .BI "\-bnum "num specify the number of the elements of the bucket array. .TP .B \-bin treat records as Base64 format. .SH EXAMPLES For example, to make a database to search `/etc/password' by a user name, perform the following command. .br \fB cat /etc/passwd | tr ':' '\t' | dptsv import casket\fP .br .PP Thus, to retrieve the information of a user `mikio', perform the following command. .br \fB dpmgr get casket mikio\fP .br .SH SEE ALSO .BR qdbm (3), .BR dpmgr (1), .BR dpopen (3). .SH AUTHOR QDBM was written by Mikio Hirabayashi . .PP This manual page was written by Fumitoshi UKAI , for the Debian project (but may be used by others). qdbm-1.8.78/man/hvmgr.10000644000175000017500000000524311426314221013524 0ustar mikiomikio.\" Hey, EMACS: -*- nroff -*- .\" First parameter, NAME, should be all caps .\" Second parameter, SECTION, should be 1-8, maybe w/ subsection .\" other parameters are allowed: see man(7), man(1) .TH HVMGR 1 "2005-05-23" "Man Page" "Quick Database Manager" .\" Please adjust this date whenever revising the manpage. .\" .\" Some roff macros, for reference: .\" .nh disable hyphenation .\" .hy enable hyphenation .\" .ad l left justify .\" .ad b justify to both left and right margins .\" .nf disable filling .\" .fi enable filling .\" .br insert line break .\" .sp insert n+1 empty lines .\" for manpage-specific macros, see man(7) .SH NAME hvmgr \- administration utility for QDBM Hovel .SH SYNOPSIS .B hvmgr create .RI "[-qdbm " "bnum dnum " "] [-s] " name .br .B hvmgr store .RI "[-qdbm] [-kx] [-vx|-vf] [-insert] " name " " key " " val .br .B hvmgr delete .RI "[-qdbm] [-kx] " name " " key .br .B hvmgr fetch .RI "[-qdbm] [-kx] [-ox] [-n] " name " " key .br .B hvmgr list .RI "[-qdbm] [-ox] " name .br .B hvmgr optimize .RI "[-qdbm] " name .SH DESCRIPTION This manual page documents briefly the .B hvmgr commands. .PP .\" TeX users may be more comfortable with the \fB\fP and .\" \fI\fP escape sequences to invode bold face and italics, .\" respectively. \fBhvmgr\fP is a utility for debugging Hovel and its applications. It features editing and checking of a database. It can be used for database applications with shell scripts. This command is used in the above format. \fIname\fP specifies a database name. \fIkey\fP specifies the key of a record. \fIval\fP specifies the value of a record. .SH OPTIONS A summary of options is included below. For a complete description, see the file:///usr/share/doc/qdbm-doc/spex.html#hovelcli. .TP .BI "\-qdbm [" bnum " " dnum "]" use `gdbm_open2' to open the database. \fIbnum\fP specifies the number of the elements of the bucket array. \fIdnum\fP specifies the number of division of the database. .TP .B \-s make the file sparse. .TP .B \-kx treat \fIkey\fP as a binary expression of hexadecimal notation. .TP .B \-vx treat \fIval\fP as a binary expression of hexadecimal notation. .TP .B \-vf read the value from a file specified with \fIval\fP. .TP .B \-insert specify the storing mode for `GDBM_INSERT'. .TP .B \-ox treat the output as a binary expression of hexadecimal notation. .TP .B \-n do not output the trailing newline. .SH SEE ALSO .BR qdbm (3), .BR hovel (3). .SH AUTHOR QDBM was written by Mikio Hirabayashi . .PP This manual page was written by Fumitoshi UKAI , for the Debian project (but may be used by others). qdbm-1.8.78/man/crtest.10000644000175000017500000000374011426314234013711 0ustar mikiomikio.TH CRTEST 1 "2005-06-01" "Man Page" "Quick Database Manager" .SH NAME crtest \- test cases for QDBM Curia .SH SYNOPSIS .PP .B crtest write .RI "[-s] [-lob] " name " " rnum " " bnum " " dnum .br .B crtest read .RI "[-wb] [-lob] " name .br .B crtest rcat .RI "[-c] " name " " rnum " " bnum " " dnum " " pnum " " align .br .B crtest combo .I name .br .B crtest wicked .RI "[-c] " name " "rnum .SH DESCRIPTION .PP The command `crtest' is a utility for facility test and performance test. Check a database generated by the command or measure the execution time of the command. This command is used in the following format. `name' specifies a database name. `rnum' specifies the number of records. `bnum' specifies the number of elements of a bucket array. `dnum' specifies the number of division of a database. `pnum' specifies the number of patterns of the keys. `align' specifies the basic size of alignment. `fbpsiz' specifies the size of the free block pool. .PP .TP .B crtest write [-s] [-lob] name rnum bnum dnum Store records with keys of 8 bytes. They change as `00000001', `00000002'... .TP .B crtest read [-wb] [-lob] name Retrieve all records of the database above. .TP .B crtest rcat [-c] name rnum bnum dnum pnum align fbpsiz Store records with partway duplicated keys using concatenate mode. .TP .B crtest combo name Perform combination test of various operations. .TP .B crtest wicked [-c] name rnum Perform updating operations selected at random. .PP Options feature the following. .PP .RS .B -s : make the files sparse. .br .B -lob : handle large objects. .br .B -wb : use the function `crgetwb' instead of the function `crget'. .br .B -c : perform comparison test with map of Cabin. .RE .PP This command returns 0 on success, another on failure. The environment variable `QDBMDBGFD' specifies the file descriptor to output the history of updating the variable `dpecode'. .SH SEE ALSO .PP .BR qdbm (3), .BR curia (3) .SH AUTHOR QDBM was written by Mikio Hirabayashi . qdbm-1.8.78/man/dptest.10000644000175000017500000000353211426314225013707 0ustar mikiomikio.TH DPTEST 1 "2005-06-01" "Man Page" "Quick Database Manager" .SH NAME dptest \- test cases for QDBM Depot .SH SYNOPSIS .PP .B dptest write .RI "[-s] " name " " rnum " " bnum .br .B dptest read .RI "[-wb] " name .br .B dptest rcat .RI "[-c] " name " " rnum " " bnum " " pnum " " align .br .B dptest combo .I name .br .B dptest wicked .RI "[-c] " name " " rnum .SH DESCRIPTION .PP The command `dptest' is a utility for facility test and performance test. Check a database generated by the command or measure the execution time of the command. This command is used in the following format. `name' specifies a database name. `rnum' specifies the number of the records. `bnum' specifies the number of the elements of the bucket array. `pnum' specifies the number of patterns of the keys. `align' specifies the basic size of alignment. `fbpsiz' specifies the size of the free block pool. .PP .TP .B dptest write [-s] name rnum bnum Store records with keys of 8 bytes. They change as `00000001', `00000002'... .TP .B dptest read [-wb] name Retrieve all records of the database above. .TP .B dptest rcat [-c] name rnum bnum pnum align fbpsiz Store records with partway duplicated keys using concatenate mode. .TP .B dptest combo name Perform combination test of various operations. .TP .B dptest wicked [-c] name rnum Perform updating operations selected at random. .RE .PP Options feature the following. .PP .RS .B -s : make the file sparse. .br .B -wb : use the function `dpgetwb' instead of the function `dpget'. .br .B -c : perform comparison test with map of Cabin. .RE .PP This command returns 0 on success, another on failure. The environment variable `QDBMDBGFD' specifies the file descriptor to output the history of updating the variable `dpecode'. .SH SEE ALSO .PP .BR qdbm (3), .BR depot (3) .SH AUTHOR QDBM was written by Mikio Hirabayashi . qdbm-1.8.78/man/curia.30000644000175000017500000006132710573416637013533 0ustar mikiomikio.TH CURIA 3 "2004-04-22" "Man Page" "Quick Database Manager" .SH NAME Curia \- the extended API of QDBM .SH SYNOPSIS .PP .B #include .br .B #include .br .B #include .PP .B CURIA *cropen(const char *name, int omode, int bnum, int dnum); .PP .B int crclose(CURIA *curia); .PP .B int crput(CURIA *curia, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int dmode); .PP .B int crout(CURIA *curia, const char *kbuf, int ksiz); .PP .B char *crget(CURIA *curia, const char *kbuf, int ksiz, int start, int max, int *sp); .PP .B int crgetwb(CURIA *curia, const char *kbuf, int ksiz, int start, int max, char *vbuf); .PP .B int crvsiz(CURIA *curia, const char *kbuf, int ksiz); .PP .B int criterinit(CURIA *curia); .PP .B char *criternext(CURIA *curia, int *sp); .PP .B int crsetalign(CURIA *curia, int align); .PP .B int crsetfbpsiz(CURIA *curia, int size); .PP .B int crsync(CURIA *curia); .PP .B int croptimize(CURIA *curia, int bnum); .PP .B char *crname(CURIA *curia); .PP .B int crfsiz(CURIA *curia); .PP .B double crfsizd(CURIA *curia); .PP .B int crbnum(CURIA *curia); .PP .B int crbusenum(CURIA *curia); .PP .B int crrnum(CURIA *curia); .PP .B int crwritable(CURIA *curia); .PP .B int crfatalerror(CURIA *curia); .PP .B int crinode(CURIA *curia); .PP .B time_t crmtime(CURIA *curia); .PP .B int crremove(const char *name); .PP .B int crrepair(const char *name); .PP .B int crexportdb(CURIA *curia, const char *name); .PP .B int crimportdb(CURIA *curia, const char *name); .PP .B char *crsnaffle(const char *name, const char *kbuf, int ksiz, int *sp); .PP .B int crputlob(CURIA *curia, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int dmode); .PP .B int croutlob(CURIA *curia, const char *kbuf, int ksiz); .PP .B char *crgetlob(CURIA *curia, const char *kbuf, int ksiz, int start, int max, int *sp); .PP .B int crgetlobfd(CURIA *curia, const char *kbuf, int ksiz); .PP .B int crvsizlob(CURIA *curia, const char *kbuf, int ksiz); .PP .B int crrnumlob(CURIA *curia); .SH DESCRIPTION .PP Curia is the extended API of QDBM. It provides routines for managing multiple database files in a directory. Restrictions of some file systems that the size of each file is limited are escaped by dividing a database file into two or more. If the database files deploy on multiple devices, the scalability is improved. .PP Although Depot creates a database with a file name, Curia creates a database with a directory name. A database file named as `depot' is placed in the specified directory. Although it keeps the attribute of the database, it does not keep the entities of the records. Besides, sub directories are created by the number of division of the database, named with 4 digits. The database files are placed in the subdirectories. The entities of the records are stored in the database file. For example, in the case that a database directory named as `casket' and the number of division is 3, `casket/depot', `casket/0001/depot', `casket/0002/depot' and `casket/0003/depot' are created. No error occurs even if the namesake directory exists when creating a database. So, if sub directories exists and some devices are mounted on the sub directories, the database files deploy on the multiple devices. It is possible for the database files to deploy on multiple file servers using NFS and so on. .PP Curia features managing large objects. Although usual records are stored in some database files, records of large objects are stored in individual files. Because the files of large objects are deployed in different directories named with the hash values, the access speed is part\-way robust although it is slower than the speed of usual records. Large and not often accessed data should be secluded as large objects. By doing this, the access speed of usual records is improved. The directory hierarchies of large objects are placed in the directory named as `lob' in the sub directories of the database. Because the key spaces of the usual records and the large objects are different, the operations keep out of each other. .PP In order to use Curia, you should include `depot.h', `curia.h' and `stdlib.h' in the source files. Usually, the following description will be near the beginning of a source file. .PP .RS .B #include .br .B #include .br .B #include .RE .PP A pointer to `CURIA' is used as a database handle. It is like that some file I/O routines of `stdio.h' use a pointer to `FILE'. A database handle is opened with the function `cropen' and closed with `crclose'. You should not refer directly to any member of the handle. If a fatal error occurs in a database, any access method via the handle except `crclose' will not work and return error status. Although a process is allowed to use multiple database handles at the same time, handles of the same database directory should not be used. .PP Curia also assign the external variable `dpecode' with the error code. The function `dperrmsg' is used in order to get the message of the error code. .PP The function `cropen' is used in order to get a database handle. .TP .B CURIA *cropen(const char *name, int omode, int bnum, int dnum); `name' specifies the name of a database directory. `omode' specifies the connection mode: `CR_OWRITER' as a writer, `CR_OREADER' as a reader. If the mode is `CR_OWRITER', the following may be added by bitwise or: `CR_OCREAT', which means it creates a new database if not exist, `CR_OTRUNC', which means it creates a new database regardless if one exists. Both of `CR_OREADER' and `CR_OWRITER' can be added to by bitwise or: `CR_ONOLCK', which means it opens a database directory without file locking, or `CR_OLCKNB', which means locking is performed without blocking. `CR_OCREAT' can be added to by bitwise or: `CR_OSPARSE', which means it creates database files as sparse files. `bnum' specifies the number of elements of each bucket array. If it is not more than 0, the default value is specified. The size of each bucket array is determined on creating, and can not be changed except for by optimization of the database. Suggested size of each bucket array is about from 0.5 to 4 times of the number of all records to store. `dnum' specifies the number of division of the database. If it is not more than 0, the default value is specified. The number of division can not be changed from the initial value. The max number of division is 512. The return value is the database handle or `NULL' if it is not successful. While connecting as a writer, an exclusive lock is invoked to the database directory. While connecting as a reader, a shared lock is invoked to the database directory. The thread blocks until the lock is achieved. If `CR_ONOLCK' is used, the application is responsible for exclusion control. .PP The function `crclose' is used in order to close a database handle. .TP .B int crclose(CURIA *curia); `curia' specifies a database handle. If successful, the return value is true, else, it is false. Because the region of a closed handle is released, it becomes impossible to use the handle. Updating a database is assured to be written when the handle is closed. If a writer opens a database but does not close it appropriately, the database will be broken. .PP The function `crput' is used in order to store a record. .TP .B int crput(CURIA *curia, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int dmode); `curia' specifies a database handle connected as a writer. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `vbuf' specifies the pointer to the region of a value. `vsiz' specifies the size of the region of the value. If it is negative, the size is assigned with `strlen(vbuf)'. `dmode' specifies behavior when the key overlaps, by the following values: `CR_DOVER', which means the specified value overwrites the existing one, `CR_DKEEP', which means the existing value is kept, `CR_DCAT', which means the specified value is concatenated at the end of the existing value. If successful, the return value is true, else, it is false. .PP The function `crout' is used in order to delete a record. .TP .B int crout(CURIA *curia, const char *kbuf, int ksiz); `curia' specifies a database handle connected as a writer. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. If successful, the return value is true, else, it is false. false is returned when no record corresponds to the specified key. .PP The function `crget' is used in order to retrieve a record. .TP .B char *crget(CURIA *curia, const char *kbuf, int ksiz, int start, int max, int *sp); `curia' specifies a database handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `start' specifies the offset address of the beginning of the region of the value to be read. `max' specifies the max size to be read. If it is negative, the size to read is unlimited. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the region of the value of the corresponding record, else, it is `NULL'. `NULL' is returned when no record corresponds to the specified key or the size of the value of the corresponding record is less than `start'. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. .PP The function `crgetwb' is used in order to retrieve a record and write the value into a buffer. .TP .B int crgetwb(CURIA *curia, const char *kbuf, int ksiz, int start, int max, char *vbuf); `curia' specifies a database handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `start' specifies the offset address of the beginning of the region of the value to be read. `max' specifies the max size to be read. It shuld be equal to or less than the size of the writing buffer. `vbuf' specifies the pointer to a buffer into which the value of the corresponding record is written. If successful, the return value is the size of the written data, else, it is \-1. \-1 is returned when no record corresponds to the specified key or the size of the value of the corresponding record is less than `start'. Note that no additional zero code is appended at the end of the region of the writing buffer. .PP The function `crvsiz' is used in order to get the size of the value of a record. .TP .B int crvsiz(CURIA *curia, const char *kbuf, int ksiz); `curia' specifies a database handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. If successful, the return value is the size of the value of the corresponding record, else, it is \-1. Because this function does not read the entity of a record, it is faster than `crget'. .PP The function `criterinit' is used in order to initialize the iterator of a database handle. .TP .B int criterinit(CURIA *curia); `curia' specifies a database handle. If successful, the return value is true, else, it is false. The iterator is used in order to access the key of every record stored in a database. .PP The function `criternext' is used in order to get the next key of the iterator. .TP .B char *criternext(CURIA *curia, int *sp); `curia' specifies a database handle. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the region of the next key, else, it is `NULL'. `NULL' is returned when no record is to be get out of the iterator. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. It is possible to access every record by iteration of calling this function. However, it is not assured if updating the database is occurred while the iteration. Besides, the order of this traversal access method is arbitrary, so it is not assured that the order of storing matches the one of the traversal access. .PP The function `crsetalign' is used in order to set alignment of a database handle. .TP .B int crsetalign(CURIA *curia, int align); `curia' specifies a database handle connected as a writer. `align' specifies the size of alignment. If successful, the return value is true, else, it is false. If alignment is set to a database, the efficiency of overwriting values is improved. The size of alignment is suggested to be average size of the values of the records to be stored. If alignment is positive, padding whose size is multiple number of the alignment is placed. If alignment is negative, as `vsiz' is the size of a value, the size of padding is calculated with `(vsiz / pow(2, abs(align) \- 1))'. Because alignment setting is not saved in a database, you should specify alignment every opening a database. .PP The function `crsetfbpsiz' is used in order to set the size of the free block pool of a database handle. .TP .B int crsetfbpsiz(CURIA *curia, int size); `curia' specifies a database handle connected as a writer. `size' specifies the size of the free block pool of a database. If successful, the return value is true, else, it is false. The default size of the free block pool is 16. If the size is greater, the space efficiency of overwriting values is improved with the time efficiency sacrificed. .PP The function `crsync' is used in order to synchronize updating contents with the files and the devices. .TP .B int crsync(CURIA *curia); `curia' specifies a database handle connected as a writer. If successful, the return value is true, else, it is false. This function is useful when another process uses the connected database directory. .PP The function `croptimize' is used in order to optimize a database. .TP .B int croptimize(CURIA *curia, int bnum); `curia' specifies a database handle connected as a writer. `bnum' specifies the number of the elements of each bucket array. If it is not more than 0, the default value is specified. In an alternating succession of deleting and storing with overwrite or concatenate, dispensable regions accumulate. This function is useful to do away with them. .PP The function `crname' is used in order to get the name of a database. .TP .B char *crname(CURIA *curia); `curia' specifies a database handle. If successful, the return value is the pointer to the region of the name of the database, else, it is `NULL'. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. .PP The function `crfsiz' is used in order to get the total size of database files. .TP .B int crfsiz(CURIA *curia); `curia' specifies a database handle. If successful, the return value is the total size of the database files, else, it is \-1. If the total size is more than 2GB, the return value overflows. .PP The function `crfsizd' is used in order to get the total size of database files as double\-precision floating\-point number. .TP .B double crfsizd(CURIA *curia); `curia' specifies a database handle. If successful, the return value is the total size of the database files, else, it is \-1.0. .PP The function `crbnum' is used in order to get the total number of the elements of each bucket array. .TP .B int crbnum(CURIA *curia); `curia' specifies a database handle. If successful, the return value is the total number of the elements of each bucket array, else, it is \-1. .PP The function `crbusenum' is used in order to get the total number of the used elements of each bucket array. .TP .B int crbusenum(CURIA *curia); `curia' specifies a database handle. If successful, the return value is the total number of the used elements of each bucket array, else, it is \-1. This function is inefficient because it accesses all elements of each bucket array. .PP The function `crrnum' is used in order to get the number of the records stored in a database. .TP .B int crrnum(CURIA *curia); `curia' specifies a database handle. If successful, the return value is the number of the records stored in the database, else, it is \-1. .PP The function `crwritable' is used in order to check whether a database handle is a writer or not. .TP .B int crwritable(CURIA *curia); `curia' specifies a database handle. The return value is true if the handle is a writer, false if not. .PP The function `crfatalerror' is used in order to check whether a database has a fatal error or not. .TP .B int crfatalerror(CURIA *curia); `curia' specifies a database handle. The return value is true if the database has a fatal error, false if not. .PP The function `crinode' is used in order to get the inode number of a database directory. .TP .B int crinode(CURIA *curia); `curia' specifies a database handle. The return value is the inode number of the database directory. .PP The function `crmtime' is used in order to get the last modified time of a database. .TP .B time_t crmtime(CURIA *curia); `curia' specifies a database handle. The return value is the last modified time of the database. .PP The function `crremove' is used in order to remove a database directory. .TP .B int crremove(const char *name); `name' specifies the name of a database directory. If successful, the return value is true, else, it is false. .PP The function `crrepair' is used in order to repair a broken database directory. .TP .B int crrepair(const char *name); `name' specifies the name of a database directory. If successful, the return value is true, else, it is false. There is no guarantee that all records in a repaired database directory correspond to the original or expected state. .PP The function `crexportdb' is used in order to dump all records as endian independent data. .TP .B int crexportdb(CURIA *curia, const char *name); `curia' specifies a database handle. `name' specifies the name of an output directory. If successful, the return value is true, else, it is false. Note that large objects are ignored. .PP The function `crimportdb' is used in order to load all records from endian independent data. .TP .B int crimportdb(CURIA *curia, const char *name); `curia' specifies a database handle connected as a writer. The database of the handle must be empty. `name' specifies the name of an input directory. If successful, the return value is true, else, it is false. Note that large objects are ignored. .PP The function `crsnaffle' is used in order to retrieve a record directly from a database directory. .TP .B char *crsnaffle(const char *name, const char *kbuf, int ksiz, int *sp); `name' specifies the name of a database directory. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the region of the value of the corresponding record, else, it is `NULL'. `NULL' is returned when no record corresponds to the specified key. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. Although this function can be used even while the database directory is locked by another process, it is not assured that recent updated is reflected. .PP The function `crputlob' is used in order to store a large object. .TP .B int crputlob(CURIA *curia, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int dmode); `curia' specifies a database handle connected as a writer. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `vbuf' specifies the pointer to the region of a value. `vsiz' specifies the size of the region of the value. If it is negative, the size is assigned with `strlen(vbuf)'. `dmode' specifies behavior when the key overlaps, by the following values: `CR_DOVER', which means the specified value overwrites the existing one, `CR_DKEEP', which means the existing value is kept, `CR_DCAT', which means the specified value is concatenated at the end of the existing value. If successful, the return value is true, else, it is false. .PP The function `croutlob' is used in order to delete a large object. .TP .B int croutlob(CURIA *curia, const char *kbuf, int ksiz); `curia' specifies a database handle connected as a writer. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. If successful, the return value is true, else, it is false. false is returned when no large object corresponds to the specified key. .PP The function `crgetlob' is used in order to retrieve a large object. .TP .B char *crgetlob(CURIA *curia, const char *kbuf, int ksiz, int start, int max, int *sp); `curia' specifies a database handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `start' specifies the offset address of the beginning of the region of the value to be read. `max' specifies the max size to be read. If it is negative, the size to read is unlimited. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the region of the value of the corresponding large object, else, it is `NULL'. `NULL' is returned when no large object corresponds to the specified key or the size of the value of the corresponding large object is less than `start'. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. .PP The function `crgetlobfd' is used in order to get the file descriptor of a large object. .TP .B int crgetlobfd(CURIA *curia, const char *kbuf, int ksiz); `curia' specifies a database handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. If successful, the return value is the file descriptor of the corresponding large object, else, it is \-1. \-1 is returned when no large object corresponds to the specified key. The returned file descriptor is opened with the `open' call. If the database handle was opened as a writer, the descriptor is writable (O_RDWR), else, it is not writable (O_RDONLY). The descriptor should be closed with the `close' call if it is no longer in use. .PP The function `crvsizlob' is used in order to get the size of the value of a large object. .TP .B int crvsizlob(CURIA *curia, const char *kbuf, int ksiz); `curia' specifies a database handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. If successful, the return value is the size of the value of the corresponding large object, else, it is \-1. Because this function does not read the entity of a large object, it is faster than `crgetlob'. .PP The function `crrnumlob' is used in order to get the number of the large objects stored in a database. .TP .B int crrnumlob(CURIA *curia); `curia' specifies a database handle. If successful, the return value is the number of the large objects stored in the database, else, it is \-1. .PP If QDBM was built with POSIX thread enabled, the global variable `dpecode' is treated as thread specific data, and functions of Curia are reentrant. In that case, they are thread\-safe as long as a handle is not accessed by threads at the same time, on the assumption that `errno', `malloc', and so on are thread\-safe. .SH SEE ALSO .PP .BR qdbm (3), .BR depot (3), .BR relic (3), .BR hovel (3), .BR cabin (3), .BR villa (3), .BR odeum (3), .BR ndbm (3), .BR gdbm (3) qdbm-1.8.78/man/odmgr.10000644000175000017500000000632311426314211013510 0ustar mikiomikio.\" Hey, EMACS: -*- nroff -*- .\" First parameter, NAME, should be all caps .\" Second parameter, SECTION, should be 1-8, maybe w/ subsection .\" other parameters are allowed: see man(7), man(1) .TH ODMGR 1 "2005-05-23" "Man Page" "Quick Database Manager" .\" Please adjust this date whenever revising the manpage. .\" .\" Some roff macros, for reference: .\" .nh disable hyphenation .\" .hy enable hyphenation .\" .ad l left justify .\" .ad b justify to both left and right margins .\" .nf disable filling .\" .fi enable filling .\" .br insert line break .\" .sp insert n+1 empty lines .\" for manpage-specific macros, see man(7) .SH NAME odmgr \- administration utility for QDBM Odeum .SH SYNOPSIS .B odmgr create .I name .br .B odmgr put .RI "[-uri " str "] [-title " str "] [-author " str "] [-date " str "] [-wmax " num "] [-keep] " name " [" file "]" .br .B odmgr out .RI "[-id] " name " " expr .br .B odmgr get .RI "[-id] [-t|-h] " name " " expr .br .B odmgr search .RI "[-max " num "] [-or] [-idf] [-t|-h|-n] " name " " words... .br .B odmgr list .RI "[-t|-h] " name .br .B odmgr optimize .I name .br .B odmgr inform .I name .br .B odmgr merge .I name elems... .br .B odmgr remove .I name .br .B odmgr break .RI "[-h|-k|-s] [" file "]" .br .B odmgr version .SH DESCRIPTION This manual page documents briefly the .B odmgr commands. .PP .\" TeX users may be more comfortable with the \fB\fP and .\" \fI\fP escape sequences to invode bold face and italics, .\" respectively. \fBodmgr\fP is a utility for debugging Odeum and its applications. It features editing and checking of a database. It can be used for full-text search systems with shell scripts. This command is used in the above format. \fIname\fP specifies a database name. \fIfile\fP specifies a file name, \fIexpr\fP specifies the URI or the ID number of a document, \fIwords\fP specifies searching words. \fIelems\fP specifies element databases. .SH OPTIONS A summary of options is included below. For a complete description, see the file:///usr/share/doc/qdbm-doc/spex.html#odeumcli . .TP .BI "\-uri " specify the URI of the document explicitly. .TP .BI "\-title " str specify the title of the document. .TP .BI "\-author " str specify the author of the document. .TP .BI "\-date " str specify the modified date of the document. .TP .BI "\-wmax " num specify the max number of words to be stored. .TP .B \-keep the storing mode is not to be overwrite. .TP .B \-id specify a document not by a URI but by an ID number. .TP .B \-t output the details of a document in tab separated format. .TP .B \-h output the details of a document in human-readable format. .TP .B \-k output keywords of a document. .TP .B \-s output summary of a document. .TP .BI "\-max " num specify the max number of documents of the output. .TP .B \-or perform OR search, nut AND search. .TP .B \-idf tune scores with IDF. .TP .B \-n show ID numbers and scores only. .SH SEE ALSO .BR qdbm (3), .BR odidx (1), .BR odeum (3). .BR odopen (3). .SH AUTHOR QDBM was written by Mikio Hirabayashi . .PP This manual page was written by Fumitoshi UKAI , for the Debian project (but may be used by others). qdbm-1.8.78/man/rltest.10000644000175000017500000000152111426314176013722 0ustar mikiomikio.TH RLTEST 1 "2005-06-01" "Man Page" "Quick Database Manager" .SH NAME rltest \- test cases for QDBM Relic .SH SYNOPSIS .PP .B rltest write .I name rnum .br .B rltest read .I name rnum .SH DESCRIPTION .PP The command `rltest' is a utility for facility test and performance test. Check a database generated by the command or measure the execution time of the command. This command is used in the following format. `name' specifies a database name. `rnum' specifies the number of records. .PP .TP .B rltest write name rnum Store records with keys of 8 bytes. They change as `00000001', `00000002'... .TP .B rltest read name rnum Retrieve records of the database above. .PP This command returns 0 on success, another on failure. .SH SEE ALSO .PP .BR qdbm (3), .BR relic (3) .SH AUTHOR QDBM was written by Mikio Hirabayashi . qdbm-1.8.78/man/crtsv.10000644000175000017500000000522311426314232013542 0ustar mikiomikio.\" Hey, EMACS: -*- nroff -*- .\" First parameter, NAME, should be all caps .\" Second parameter, SECTION, should be 1-8, maybe w/ subsection .\" other parameters are allowed: see man(7), man(1) .TH CRTSV 1 "2005-05-23" "Man Page" "Quick Database Manager" .\" Please adjust this date whenever revising the manpage. .\" .\" Some roff macros, for reference: .\" .nh disable hyphenation .\" .hy enable hyphenation .\" .ad l left justify .\" .ad b justify to both left and right margins .\" .nf disable filling .\" .fi enable filling .\" .br insert line break .\" .sp insert n+1 empty lines .\" for manpage-specific macros, see man(7) .SH NAME crtsv \- mutual converter between TSV and QDBM Curia database .SH SYNOPSIS .B crtsv import .RI "[-bnum " num "] [-dnum " num "] [-bin] " name .br .B crtsv export .RI "[-bin] " name .SH DESCRIPTION This manual page documents briefly the .B crtsv commands. .PP .\" TeX users may be more comfortable with the \fB\fP and .\" \fI\fP escape sequences to invode bold face and italics, .\" respectively. The command \fBcrtsv\fP features mutual conversion between a database of Curia and a TSV text. This command is useful when data exchange with another version of QDBM or another DBM, or when data exchange between systems which have different byte orders. This command is used in the above format. \fIname\fP specifies a database name. The subcommand \fBexport\fP reads TSV data from the standard input. If a key overlaps, the latter is adopted. \fB-bnum\fP specifies the number of the elements of the bucket array. \fB-dnum\fP specifies the number of division of the database. The subcommand \fBimport\fP writes TSV data to the standard output. .SH OPTIONS A summary of options is included below. For a complete description, see the file:///usr/share/doc/qdbm-doc/spex.html#curiacli. .TP .BI "\-bnum " num specify the number of the elements of the bucket array. .TP .BI "\-dnum " num specify the number of division of the database. .TP .B \-bin treat records as Base64 format. .SH EXAMPLES For example, to make a database to search `/etc/password' by a user name, perform the following command. .br \fB cat /etc/passwd | tr ':' '\t' | crtsv import casket\fP .br .PP Thus, to retrieve the information of a user `mikio', perform the following command. .br \fB crmgr get casket mikio\fP .br .SH SEE ALSO .BR qdbm (3), .BR crmgr (1), .BR curia (3), .BR cropen (3). .SH AUTHOR QDBM was written by Mikio Hirabayashi . .PP This manual page was written by Fumitoshi UKAI , for the Debian project (but may be used by others). qdbm-1.8.78/man/rlmgr.10000644000175000017500000000450611426314200013522 0ustar mikiomikio.\" Hey, EMACS: -*- nroff -*- .\" First parameter, NAME, should be all caps .\" Second parameter, SECTION, should be 1-8, maybe w/ subsection .\" other parameters are allowed: see man(7), man(1) .TH RLMGR 1 "2005-05-23" "Man Page" "Quick Database Manager" .\" Please adjust this date whenever revising the manpage. .\" .\" Some roff macros, for reference: .\" .nh disable hyphenation .\" .hy enable hyphenation .\" .ad l left justify .\" .ad b justify to both left and right margins .\" .nf disable filling .\" .fi enable filling .\" .br insert line break .\" .sp insert n+1 empty lines .\" for manpage-specific macros, see man(7) .SH NAME rlmgr \- administration utility for QDBM Relic .SH SYNOPSIS .B rlmgr create .I name .br .B rlmgr store .RI "[-kx] [-vx|-vf] [-insert] " name " " key " " val .br .B rlmgr delete .RI "[-kx] " name " " key .br .B rlmgr fetch .RI "[-kx] [-ox] [-n] " name " " key .br .B rlmgr list .RI "[-ox] " name .SH DESCRIPTION This manual page documents briefly the .B rlmgr commands. .PP .\" TeX users may be more comfortable with the \fB\fP and .\" \fI\fP escape sequences to invode bold face and italics, .\" respectively. \fBrlmgr\fP is a utility for debugging Relic and its applications. It features editing and checking of a database. It can be used for database applications with shell scripts. This command is used in the above format. \fIname\fP specifies a database name. \fIkey\fP specifies the key of a record. \fIval\fP specifies the value of a record. .SH OPTIONS A summary of options is included below. For a complete description, see the file:///usr/share/doc/qdbm-doc/spex.html#reliccli. .TP .B \-kx treat \fIkey\fP as a binary expression of hexadecimal notation. .TP .B \-vx treat \fIval\fP as a binary expression of hexadecimal notation. .TP .B \-vf read the value from a file specified with \fIval\fP. .TP .B \-insert specify the storing mode for `DBM_INSERT'. .TP .B \-ox treat the output as a binary expression of hexadecimal notation. .TP .B \-n do not output the tailing newline. .SH SEE ALSO .BR qdbm (3), .BR relic (3). .SH AUTHOR QDBM was written by Mikio Hirabayashi . .PP This manual page was written by Fumitoshi UKAI , for the Debian project (but may be used by others). qdbm-1.8.78/man/vlopen.30000644000175000017500000000002110573416637013713 0ustar mikiomikio.so man3/villa.3 qdbm-1.8.78/man/cbtest.10000644000175000017500000000227611426314241013672 0ustar mikiomikio.TH CBTEST 1 "2005-06-01" "Man Page" "Quick Database Manager" .SH NAME cbtest \- test cases for QDBM Cabin .SH SYNOPSIS .PP .B cbtest sort .RI "[-d] " rnum .br .B cbtest strstr .RI "[-d] " rnum .br .B cbtest list .RI "[-d] " rnum .br .B cbtest map .RI "[-d] " rnum .br .B cbtest wicked .I rnum .br .B cbtest misc .SH DESCRIPTION .PP The command `cbtest' is a utility for facility test and performance test. Measure the execution time of the command. This command is used in the following format. `rnum' specifies the number of records. .PP .TP .B cbtest sort [-d] rnum Perform test of sorting algorithms. .TP .B cbtest sort [-d] rnum Perform test of string locating algorithms. .TP .B cbtest list [-d] rnum Perform writing test of list. .TP .B cbtest map [-d] rnum Perform writing test of map. .TP .B cbtest wicked rnum Perform updating operations of list and map selected at random. .TP .B cbtest misc Perform test of miscellaneous routines. .PP Options feature the following. .PP .RS .B -d : read and show data of the result. .RE .PP This command returns 0 on success, another on failure. .SH SEE ALSO .PP .BR qdbm (3), .BR cabin (3) .SH AUTHOR QDBM was written by Mikio Hirabayashi . qdbm-1.8.78/man/dpopen.30000644000175000017500000000002110573416637013675 0ustar mikiomikio.so man3/depot.3 qdbm-1.8.78/man/vista.30000644000175000017500000000002110573416637013536 0ustar mikiomikio.so man3/villa.3 qdbm-1.8.78/man/odeum.30000644000175000017500000007352110573416637013540 0ustar mikiomikio.TH ODEUM 3 "2004-04-22" "Man Page" "Quick Database Manager" .SH NAME Odeum \- the inverted API of QDBM .SH SYNOPSIS .PP .B #include .br .B #include .br .B #include .br .B #include .PP .B typedef struct { int id; int score; } ODPAIR; .PP .B ODEUM *odopen(const char *name, int omode); .PP .B int odclose(ODEUM *odeum); .PP .B int odput(ODEUM *odeum, const ODDOC *doc, int wmax, int over); .PP .B int odout(ODEUM *odeum, const char *uri); .PP .B int odoutbyid(ODEUM *odeum, int id); .PP .B ODDOC *odget(ODEUM *odeum, const char *uri); .PP .B ODDOC *odgetbyid(ODEUM *odeum, int id); .PP .B int odgetidbyuri(ODEUM *odeum, const char *uri); .PP .B int odcheck(ODEUM *odeum, int id); .PP .B ODPAIR *odsearch(ODEUM *odeum, const char *word, int max, int *np); .PP .B int odsearchdnum(ODEUM *odeum, const char *word); .PP .B int oditerinit(ODEUM *odeum); .PP .B ODDOC *oditernext(ODEUM *odeum); .PP .B int odsync(ODEUM *odeum); .PP .B int odoptimize(ODEUM *odeum); .PP .B char *odname(ODEUM *odeum); .PP .B double odfsiz(ODEUM *odeum); .PP .B int odbnum(ODEUM *odeum); .PP .B int odbusenum(ODEUM *odeum); .PP .B int oddnum(ODEUM *odeum); .PP .B int odwnum(ODEUM *odeum); .PP .B int odwritable(ODEUM *odeum); .PP .B int odfatalerror(ODEUM *odeum); .PP .B int odinode(ODEUM *odeum); .PP .B time_t odmtime(ODEUM *odeum); .PP .B int odmerge(const char *name, const CBLIST *elemnames); .PP .B int odremove(const char *name); .PP .B ODDOC *oddocopen(const char *uri); .PP .B void oddocclose(ODDOC *doc); .PP .B void oddocaddattr(ODDOC *doc, const char *name, const char *value); .PP .B void oddocaddword(ODDOC *doc, const char *normal, const char *asis); .PP .B int oddocid(const ODDOC *doc); .PP .B const char *oddocuri(const ODDOC *doc); .PP .B const char *oddocgetattr(const ODDOC *doc, const char *name); .PP .B const CBLIST *oddocnwords(const ODDOC *doc); .PP .B const CBLIST *oddocawords(const ODDOC *doc); .PP .B CBMAP *oddocscores(const ODDOC *doc, int max, ODEUM *odeum); .PP .B CBLIST *odbreaktext(const char *text); .PP .B char *odnormalizeword(const char *asis); .PP .B ODPAIR *odpairsand(ODPAIR *apairs, int anum, ODPAIR *bpairs, int bnum, int *np); .PP .B ODPAIR *odpairsor(ODPAIR *apairs, int anum, ODPAIR *bpairs, int bnum, int *np); .PP .B ODPAIR *odpairsnotand(ODPAIR *apairs, int anum, ODPAIR *bpairs, int bnum, int *np); .PP .B void odpairssort(ODPAIR *pairs, int pnum); .PP .B double odlogarithm(double x); .PP .B double odvectorcosine(const int *avec, const int *bvec, int vnum); .PP .B void odsettuning(int ibnum, int idnum, int cbnum, int csiz); .PP .B void odanalyzetext(ODEUM *odeum, const char *text, CBLIST *awords, CBLIST *nwords); .PP .B void odsetcharclass(ODEUM *odeum, const char *spacechars, const char *delimchars, const char *gluechars); .PP .B ODPAIR *odquery(ODEUM *odeum, const char *query, int *np, CBLIST *errors); .SH DESCRIPTION Odeum is the API which handles an inverted index. An inverted index is a data structure to retrieve a list of some documents that include one of words which were extracted from a population of documents. It is easy to realize a full\-text search system with an inverted index. Odeum provides an abstract data structure which consists of words and attributes of a document. It is used when an application stores a document into a database and when an application retrieves some documents from a database. .PP Odeum does not provide methods to extract the text from the original data of a document. It should be implemented by applications. Although Odeum provides utilities to extract words from a text, it is oriented to such languages whose words are separated with space characters as English. If an application handles such languages which need morphological analysis or N\-gram analysis as Japanese, or if an application perform more such rarefied analysis of natural languages as stemming, its own analyzing method can be adopted. Result of search is expressed as an array contains elements which are structures composed of the ID number of documents and its score. In order to search with two or more words, Odeum provides utilities of set operations. .PP Odeum is implemented, based on Curia, Cabin, and Villa. Odeum creates a database with a directory name. Some databases of Curia and Villa are placed in the specified directory. For example, `casket/docs', `casket/index', and `casket/rdocs' are created in the case that a database directory named as `casket'. `docs' is a database directory of Curia. The key of each record is the ID number of a document, and the value is such attributes as URI. `index' is a database directory of Curia. The key of each record is the normalized form of a word, and the value is an array whose element is a pair of the ID number of a document including the word and its score. `rdocs' is a database file of Villa. The key of each record is the URI of a document, and the value is its ID number. .PP In order to use Odeum, you should include `depot.h', `cabin.h', `odeum.h' and `stdlib.h' in the source files. Usually, the following description will be near the beginning of a source file. .PP .RS .B #include .br .B #include .br .B #include .br .B #include .RE .PP A pointer to `ODEUM' is used as a database handle. A database handle is opened with the function `odopen' and closed with `odclose'. You should not refer directly to any member of the handle. If a fatal error occurs in a database, any access method via the handle except `odclose' will not work and return error status. Although a process is allowed to use multiple database handles at the same time, handles of the same database file should not be used. .PP A pointer to `ODDOC' is used as a document handle. A document handle is opened with the function `oddocopen' and closed with `oddocclose'. You should not refer directly to any member of the handle. A document consists of attributes and words. Each word is expressed as a pair of a normalized form and a appearance form. .PP Odeum also assign the external variable `dpecode' with the error code. The function `dperrmsg' is used in order to get the message of the error code. .PP Structures of `ODPAIR' type is used in order to handle results of search. .TP .B typedef struct { int id; int score; } ODPAIR; `id' specifies the ID number of a document. `score' specifies the score calculated from the number of searching words in the document. .PP The function `odopen' is used in order to get a database handle. .TP .B ODEUM *odopen(const char *name, int omode); `name' specifies the name of a database directory. `omode' specifies the connection mode: `OD_OWRITER' as a writer, `OD_OREADER' as a reader. If the mode is `OD_OWRITER', the following may be added by bitwise or: `OD_OCREAT', which means it creates a new database if not exist, `OD_OTRUNC', which means it creates a new database regardless if one exists. Both of `OD_OREADER' and `OD_OWRITER' can be added to by bitwise or: `OD_ONOLCK', which means it opens a database directory without file locking, or `OD_OLCKNB', which means locking is performed without blocking. The return value is the database handle or `NULL' if it is not successful. While connecting as a writer, an exclusive lock is invoked to the database directory. While connecting as a reader, a shared lock is invoked to the database directory. The thread blocks until the lock is achieved. If `OD_ONOLCK' is used, the application is responsible for exclusion control. .PP The function `odclose' is used in order to close a database handle. .TP .B int odclose(ODEUM *odeum); `odeum' specifies a database handle. If successful, the return value is true, else, it is false. Because the region of a closed handle is released, it becomes impossible to use the handle. Updating a database is assured to be written when the handle is closed. If a writer opens a database but does not close it appropriately, the database will be broken. .PP The function `odput' is used in order to store a document. .TP .B int odput(ODEUM *odeum, const ODDOC *doc, int wmax, int over); `odeum' specifies a database handle connected as a writer. `doc' specifies a document handle. `wmax' specifies the max number of words to be stored in the document database. If it is negative, the number is unlimited. `over' specifies whether the data of the duplicated document is overwritten or not. If it is false and the URI of the document is duplicated, the function returns as an error. If successful, the return value is true, else, it is false. .PP The function `odout' is used in order to delete a document specified by a URI. .TP .B int odout(ODEUM *odeum, const char *uri); `odeum' specifies a database handle connected as a writer. `uri' specifies the string of the URI of a document. If successful, the return value is true, else, it is false. False is returned when no document corresponds to the specified URI. .PP The function `odoutbyid' is used in order to delete a document specified by an ID number. .TP .B int odoutbyid(ODEUM *odeum, int id); `odeum' specifies a database handle connected as a writer. `id' specifies the ID number of a document. If successful, the return value is true, else, it is false. False is returned when no document corresponds to the specified ID number. .PP The function `odget' is used in order to retrieve a document specified by a URI. .TP .B ODDOC *odget(ODEUM *odeum, const char *uri); `odeum' specifies a database handle. `uri' specifies the string of the URI of a document. If successful, the return value is the handle of the corresponding document, else, it is `NULL'. `NULL' is returned when no document corresponds to the specified URI. Because the handle of the return value is opened with the function `oddocopen', it should be closed with the function `oddocclose'. .PP The function `odgetbyid' is used in order to retrieve a document by an ID number. .TP .B ODDOC *odgetbyid(ODEUM *odeum, int id); `odeum' specifies a database handle. `id' specifies the ID number of a document. If successful, the return value is the handle of the corresponding document, else, it is `NULL'. `NULL' is returned when no document corresponds to the specified ID number. Because the handle of the return value is opened with the function `oddocopen', it should be closed with the function `oddocclose'. .PP The function `odgetidbyuri' is used in order to retrieve the ID of the document specified by a URI. .TP .B int odgetidbyuri(ODEUM *odeum, const char *uri); `odeum' specifies a database handle. `uri' specifies the string the URI of a document. If successful, the return value is the ID number of the document, else, it is \-1. \-1 is returned when no document corresponds to the specified URI. .PP The function `odcheck' is used in order to check whether the document specified by an ID number exists. .TP .B int odcheck(ODEUM *odeum, int id); `odeum' specifies a database handle. `id' specifies the ID number of a document. The return value is true if the document exists, else, it is false. .PP The function `odsearch' is used in order to search the inverted index for documents including a particular word. .TP .B ODPAIR *odsearch(ODEUM *odeum, const char *word, int max, int *np); `odeum' specifies a database handle. `word' specifies a searching word. `max' specifies the max number of documents to be retrieve. `np' specifies the pointer to a variable to which the number of the elements of the return value is assigned. If successful, the return value is the pointer to an array, else, it is `NULL'. Each element of the array is a pair of the ID number and the score of a document, and sorted in descending order of their scores. Even if no document corresponds to the specified word, it is not error but returns an dummy array. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. Note that each element of the array of the return value can be data of a deleted document. .PP The function `odsearchnum' is used in order to get the number of documents including a word. .TP .B int odsearchdnum(ODEUM *odeum, const char *word); `odeum' specifies a database handle. `word' specifies a searching word. If successful, the return value is the number of documents including the word, else, it is \-1. Because this function does not read the entity of the inverted index, it is faster than `odsearch'. .PP The function `oditerinit' is used in order to initialize the iterator of a database handle. .TP .B int oditerinit(ODEUM *odeum); `odeum' specifies a database handle. If successful, the return value is true, else, it is false. The iterator is used in order to access every document stored in a database. .PP The function `oditernext' is used in order to get the next key of the iterator. .TP .B ODDOC *oditernext(ODEUM *odeum); `odeum' specifies a database handle. If successful, the return value is the handle of the next document, else, it is `NULL'. `NULL' is returned when no document is to be get out of the iterator. It is possible to access every document by iteration of calling this function. However, it is not assured if updating the database is occurred while the iteration. Besides, the order of this traversal access method is arbitrary, so it is not assured that the order of string matches the one of the traversal access. Because the handle of the return value is opened with the function `oddocopen', it should be closed with the function `oddocclose'. .PP The function `odsync' is used in order to synchronize updating contents with the files and the devices. .TP .B int odsync(ODEUM *odeum); `odeum' specifies a database handle connected as a writer. If successful, the return value is true, else, it is false. This function is useful when another process uses the connected database directory. .PP The function `odoptimize' is used in order to optimize a database. .TP .B int odoptimize(ODEUM *odeum); `odeum' specifies a database handle connected as a writer. If successful, the return value is true, else, it is false. Elements of the deleted documents in the inverted index are purged. .PP The function `odname' is used in order to get the name of a database. .TP .B char *odname(ODEUM *odeum); `odeum' specifies a database handle. If successful, the return value is the pointer to the region of the name of the database, else, it is `NULL'. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. .PP The function `odfsiz' is used in order to get the total size of database files. .TP .B double odfsiz(ODEUM *odeum); `odeum' specifies a database handle. If successful, the return value is the total size of the database files, else, it is \-1.0. .PP The function `odbnum' is used in order to get the total number of the elements of the bucket arrays in the inverted index. .TP .B int odbnum(ODEUM *odeum); `odeum' specifies a database handle. If successful, the return value is the total number of the elements of the bucket arrays, else, it is \-1. .PP The function `odbusenum' is used in order to get the total number of the used elements of the bucket arrays in the inverted index. .TP .B int odbusenum(ODEUM *odeum); `odeum' specifies a database handle. If successful, the return value is the total number of the used elements of the bucket arrays, else, it is \-1. .PP The function `oddnum' is used in order to get the number of the documents stored in a database. .TP .B int oddnum(ODEUM *odeum); `odeum' specifies a database handle. If successful, the return value is the number of the documents stored in the database, else, it is \-1. .PP The function `odwnum' is used in order to get the number of the words stored in a database. .TP .B int odwnum(ODEUM *odeum); `odeum' specifies a database handle. If successful, the return value is the number of the words stored in the database, else, it is \-1. Because of the I/O buffer, the return value may be less than the hard number. .PP The function `odwritable' is used in order to check whether a database handle is a writer or not. .TP .B int odwritable(ODEUM *odeum); `odeum' specifies a database handle. The return value is true if the handle is a writer, false if not. .PP The function `odfatalerror' is used in order to check whether a database has a fatal error or not. .TP .B int odfatalerror(ODEUM *odeum); `odeum' specifies a database handle. The return value is true if the database has a fatal error, false if not. .PP The function `odinode' is used in order to get the inode number of a database directory. .TP .B int odinode(ODEUM *odeum); `odeum' specifies a database handle. The return value is the inode number of the database directory. .PP The function `odmtime' is used in order to get the last modified time of a database. .TP .B time_t odmtime(ODEUM *odeum); `odeum' specifies a database handle. The return value is the last modified time of the database. .PP The function `odmerge' is used in order to merge plural database directories. .TP .B int odmerge(const char *name, const CBLIST *elemnames); `name' specifies the name of a database directory to create. `elemnames' specifies a list of names of element databases. If successful, the return value is true, else, it is false. If two or more documents which have the same URL come in, the first one is adopted and the others are ignored. .PP The function `odremove' is used in order to remove a database directory. .TP .B int odremove(const char *name); `name' specifies the name of a database directory. If successful, the return value is true, else, it is false. A database directory can contain databases of other APIs of QDBM, they are also removed by this function. .PP The function `oddocopen' is used in order to get a document handle. .TP .B ODDOC *oddocopen(const char *uri); `uri' specifies the URI of a document. The return value is a document handle. The ID number of a new document is not defined. It is defined when the document is stored in a database. .PP The function `oddocclose' is used in order to close a document handle. .TP .B void oddocclose(ODDOC *doc); `doc' specifies a document handle. Because the region of a closed handle is released, it becomes impossible to use the handle. .PP The function `oddocaddattr' is used in order to add an attribute to a document. .TP .B void oddocaddattr(ODDOC *doc, const char *name, const char *value); `doc' specifies a document handle. `name' specifies the string of the name of an attribute. `value' specifies the string of the value of the attribute. .PP The function `oddocaddword' is used in order to add a word to a document. .TP .B void oddocaddword(ODDOC *doc, const char *normal, const char *asis); `doc' specifies a document handle. `normal' specifies the string of the normalized form of a word. Normalized forms are treated as keys of the inverted index. If the normalized form of a word is an empty string, the word is not reflected in the inverted index. `asis' specifies the string of the appearance form of the word. Appearance forms are used after the document is retrieved by an application. .PP The function `oddocid' is used in order to get the ID number of a document. .TP .B int oddocid(const ODDOC *doc); `doc' specifies a document handle. The return value is the ID number of a document. .PP The function `oddocuri' is used in order to get the URI of a document. .TP .B const char *oddocuri(const ODDOC *doc); `doc' specifies a document handle. The return value is the string of the URI of a document. .PP The function `oddocgetattr' is used in order to get the value of an attribute of a document. .TP .B const char *oddocgetattr(const ODDOC *doc, const char *name); `doc' specifies a document handle. `name' specifies the string of the name of an attribute. The return value is the string of the value of the attribute, or `NULL' if no attribute corresponds. .PP The function `oddocnwords' is used in order to get the list handle contains words in normalized form of a document. .TP .B const CBLIST *oddocnwords(const ODDOC *doc); `doc' specifies a document handle. The return value is the list handle contains words in normalized form. .PP The function `oddocawords' is used in order to get the list handle contains words in appearance form of a document. .TP .B const CBLIST *oddocawords(const ODDOC *doc); `doc' specifies a document handle. The return value is the list handle contains words in appearance form. .PP The function `oddocscores' is used in order to get the map handle contains keywords in normalized form and their scores. .TP .B CBMAP *oddocscores(const ODDOC *doc, int max, ODEUM *odeum); `doc' specifies a document handle. `max' specifies the max number of keywords to get. `odeum' specifies a database handle with which the IDF for weighting is calculate. If it is `NULL', it is not used. The return value is the map handle contains keywords and their scores. Scores are expressed as decimal strings. Because the handle of the return value is opened with the function `cbmapopen', it should be closed with the function `cbmapclose' if it is no longer in use. .PP The function `odbreaktext' is used in order to break a text into words in appearance form. .TP .B CBLIST *odbreaktext(const char *text); `text' specifies the string of a text. The return value is the list handle contains words in appearance form. Words are separated with space characters and such delimiters as period, comma and so on. Because the handle of the return value is opened with the function `cblistopen', it should be closed with the function `cblistclose' if it is no longer in use. .PP The function `odnormalizeword' is used in order to make the normalized form of a word. .TP .B char *odnormalizeword(const char *asis); `asis' specifies the string of the appearance form of a word. The return value is is the string of the normalized form of the word. Alphabets of the ASCII code are unified into lower cases. Words composed of only delimiters are treated as empty strings. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. .PP The function `odpairsand' is used in order to get the common elements of two sets of documents. .TP .B ODPAIR *odpairsand(ODPAIR *apairs, int anum, ODPAIR *bpairs, int bnum, int *np); `apairs' specifies the pointer to the former document array. `anum' specifies the number of the elements of the former document array. `bpairs' specifies the pointer to the latter document array. `bnum' specifies the number of the elements of the latter document array. `np' specifies the pointer to a variable to which the number of the elements of the return value is assigned. The return value is the pointer to a new document array whose elements commonly belong to the specified two sets. Elements of the array are sorted in descending order of their scores. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. .PP The function `odpairsor' is used in order to get the sum of elements of two sets of documents. .TP .B ODPAIR *odpairsor(ODPAIR *apairs, int anum, ODPAIR *bpairs, int bnum, int *np); `apairs' specifies the pointer to the former document array. `anum' specifies the number of the elements of the former document array. `bpairs' specifies the pointer to the latter document array. `bnum' specifies the number of the elements of the latter document array. `np' specifies the pointer to a variable to which the number of the elements of the return value is assigned. The return value is the pointer to a new document array whose elements belong to both or either of the specified two sets. Elements of the array are sorted in descending order of their scores. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. .PP The function `odpairsnotand' is used in order to get the difference set of documents. .TP .B ODPAIR *odpairsnotand(ODPAIR *apairs, int anum, ODPAIR *bpairs, int bnum, int *np); `apairs' specifies the pointer to the former document array. `anum' specifies the number of the elements of the former document array. `bpairs' specifies the pointer to the latter document array of the sum of elements. `bnum' specifies the number of the elements of the latter document array. `np' specifies the pointer to a variable to which the number of the elements of the return value is assigned. The return value is the pointer to a new document array whose elements belong to the former set but not to the latter set. Elements of the array are sorted in descending order of their scores. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. .PP The function `odpairssort' is used in order to sort a set of documents in descending order of scores. .TP .B void odpairssort(ODPAIR *pairs, int pnum); `pairs' specifies the pointer to a document array. `pnum' specifies the number of the elements of the document array. .PP The function `odlogarithm' is used in order to get the natural logarithm of a number. .TP .B double odlogarithm(double x); `x' specifies a number. The return value is the natural logarithm of the number. If the number is equal to or less than 1.0, the return value is 0.0. This function is useful when an application calculates the IDF of search results. .PP The function `odvectorcosine' is used in order to get the cosine of the angle of two vectors. .TP .B double odvectorcosine(const int *avec, const int *bvec, int vnum); `avec' specifies the pointer to one array of numbers. `bvec' specifies the pointer to the other array of numbers. `vnum' specifies the number of elements of each array. The return value is the cosine of the angle of two vectors. This function is useful when an application calculates similarity of documents. .PP The function `odsettuning' is used in order to set the global tuning parameters. .TP .B void odsettuning(int ibnum, int idnum, int cbnum, int csiz); `ibnum' specifies the number of buckets for inverted indexes. `idnum' specifies the division number of inverted index. `cbnum' specifies the number of buckets for dirty buffers. `csiz' specifies the maximum bytes to use memory for dirty buffers. The default setting is equivalent to `odsettuning(32749, 7, 262139, 8388608)'. This function should be called before opening a handle. .PP The function `odanalyzetext' is used in order to break a text into words and store appearance forms and normalized form into lists. .TP .B void odanalyzetext(ODEUM *odeum, const char *text, CBLIST *awords, CBLIST *nwords); `odeum' specifies a database handle. `text' specifies the string of a text. `awords' specifies a list handle into which appearance form is store. `nwords' specifies a list handle into which normalized form is store. If it is `NULL', it is ignored. Words are separated with space characters and such delimiters as period, comma and so on. .PP The function `odsetcharclass' is used in order to set the classes of characters used by `odanalyzetext'. .TP .B void odsetcharclass(ODEUM *odeum, const char *spacechars, const char *delimchars, const char *gluechars); `odeum' specifies a database handle. `spacechars' spacifies a string contains space characters. `delimchars' spacifies a string contains delimiter characters. `gluechars' spacifies a string contains glue characters. .PP The function `odquery' is used in order to query a database using a small boolean query language. .TP .B ODPAIR *odquery(ODEUM *odeum, const char *query, int *np, CBLIST *errors); `odeum' specifies a database handle. 'query' specifies the text of the query. `np' specifies the pointer to a variable to which the number of the elements of the return value is assigned. `errors' specifies a list handle into which error messages are stored. If it is `NULL', it is ignored. If successful, the return value is the pointer to an array, else, it is `NULL'. Each element of the array is a pair of the ID number and the score of a document, and sorted in descending order of their scores. Even if no document corresponds to the specified condition, it is not error but returns an dummy array. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. Note that each element of the array of the return value can be data of a deleted document. .PP If QDBM was built with POSIX thread enabled, the global variable `dpecode' is treated as thread specific data, and functions of Odeum are reentrant. In that case, they are thread\-safe as long as a handle is not accessed by threads at the same time, on the assumption that `errno', `malloc', and so on are thread\-safe. .PP If QDBM was built with ZLIB enabled, records in the database for document attributes are compressed. In that case, the size of the database is reduced to 30% or less. Thus, you should enable ZLIB if you use Odeum. A database of Odeum created without ZLIB enabled is not available on environment with ZLIB enabled, and vice versa. If ZLIB was not enabled but LZO, LZO is used instead. .PP The query language of the function `odquery' is a basic language following this grammar: .PP .RS expr ::= subexpr ( op subexpr )* .br subexpr ::= WORD .br subexpr ::= LPAREN expr RPAREN .RE .PP Operators are "&" (AND), "|" (OR), and "!" (NOTAND). You can use parenthesis to group sub-expressions together in order to change order of operations. The given query is broken up using the function `odanalyzetext', so if you want to specify different text breaking rules, then make sure that you at least set "&", "|", "!", "(", and ")" to be delimiter characters. Consecutive words are treated as having an implicit "&" operator between them, so "zed shaw" is actually "zed & shaw". .PP The encoding of the query text should be the same with the encoding of target documents. Moreover, each of space characters, delimiter characters, and glue characters should be single byte. .SH SEE ALSO .PP .BR qdbm (3), .BR depot (3), .BR curia (3), .BR relic (3), .BR hovel (3), .BR cabin (3), .BR villa (3), .BR ndbm (3), .BR gdbm (3) qdbm-1.8.78/man/depot.30000644000175000017500000004772410573416637013550 0ustar mikiomikio.TH DEPOT 3 "2004-04-22" "Man Page" "Quick Database Manager" .SH NAME Depot \- the basic API of QDBM .SH SYNOPSIS .PP .B #include .br .B #include .PP .B extern const char *dpversion; .PP .B extern int dpecode; .PP .B const char *dperrmsg(int ecode); .PP .B DEPOT *dpopen(const char *name, int omode, int bnum); .PP .B int dpclose(DEPOT *depot); .PP .B int dpput(DEPOT *depot, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int dmode); .PP .B int dpout(DEPOT *depot, const char *kbuf, int ksiz); .PP .B char *dpget(DEPOT *depot, const char *kbuf, int ksiz, int start, int max, int *sp); .PP .B int dpgetwb(DEPOT *depot, const char *kbuf, int ksiz, int start, int max, char *vbuf); .PP .B int dpvsiz(DEPOT *depot, const char *kbuf, int ksiz); .PP .B int dpiterinit(DEPOT *depot); .PP .B char *dpiternext(DEPOT *depot, int *sp); .PP .B int dpsetalign(DEPOT *depot, int align); .PP .B int dpsetfbpsiz(DEPOT *depot, int size); .PP .B int dpsync(DEPOT *depot); .PP .B int dpoptimize(DEPOT *depot, int bnum); .PP .B char *dpname(DEPOT *depot); .PP .B int dpfsiz(DEPOT *depot); .PP .B int dpbnum(DEPOT *depot); .PP .B int dpbusenum(DEPOT *depot); .PP .B int dprnum(DEPOT *depot); .PP .B int dpwritable(DEPOT *depot); .PP .B int dpfatalerror(DEPOT *depot); .PP .B int dpinode(DEPOT *depot); .PP .B time_t dpmtime(DEPOT *depot); .PP .B int dpfdesc(DEPOT *depot); .PP .B int dpremove(const char *name); .PP .B int dprepair(const char *name); .PP .B int dpexportdb(DEPOT *depot, const char *name); .PP .B int dpimportdb(DEPOT *depot, const char *name); .PP .B char *dpsnaffle(const char *name, const char *kbuf, int ksiz, int *sp); .PP .B int dpinnerhash(const char *kbuf, int ksiz); .PP .B int dpouterhash(const char *kbuf, int ksiz); .PP .B int dpprimenum(int num); .SH DESCRIPTION .PP Depot is the basic API of QDBM. Almost all features for managing a database provided by QDBM are implemented by Depot. Other APIs are no more than wrappers of Depot. Depot is the fastest in all APIs of QDBM. .PP In order to use Depot, you should include `depot.h' and `stdlib.h' in the source files. Usually, the following description will be near the beginning of a source file. .PP .RS .B #include .br .B #include .RE .PP A pointer to `DEPOT' is used as a database handle. It is like that some file I/O routines of `stdio.h' use a pointer to `FILE'. A database handle is opened with the function `dpopen' and closed with `dpclose'. You should not refer directly to any member of the handle. If a fatal error occurs in a database, any access method via the handle except `dpclose' will not work and return error status. Although a process is allowed to use multiple database handles at the same time, handles of the same database file should not be used. .PP The external variable `dpversion' is the string containing the version information. .TP .B extern const char *dpversion; .PP The external variable `dpecode' is assigned with the last happened error code. Refer to `depot.h' for details of the error codes. .TP .B extern int dpecode; The initial value of this variable is `DP_NOERR'. The other values are `DP_EFATAL', `DP_EMODE', `DP_EBROKEN', `DP_EKEEP', `DP_ENOITEM', `DP_EALLOC', `DP_EMAP', `DP_EOPEN', `DP_ECLOSE', `DP_ETRUNC', `DP_ESYNC', `DP_ESTAT', `DP_ESEEK', `DP_EREAD', `DP_EWRITE', `DP_ELOCK', `DP_EUNLINK', `DP_EMKDIR', `DP_ERMDIR', and `DP_EMISC'. .PP The function `dperrmsg' is used in order to get a message string corresponding to an error code. .TP .B const char *dperrmsg(int ecode); `ecode' specifies an error code. The return value is the message string of the error code. The region of the return value is not writable. .PP The function `dpopen' is used in order to get a database handle. .TP .B DEPOT *dpopen(const char *name, int omode, int bnum); `name' specifies the name of a database file. `omode' specifies the connection mode: `DP_OWRITER' as a writer, `DP_OREADER' as a reader. If the mode is `DP_OWRITER', the following may be added by bitwise or: `DP_OCREAT', which means it creates a new database if not exist, `DP_OTRUNC', which means it creates a new database regardless if one exists. Both of `DP_OREADER' and `DP_OWRITER' can be added to by bitwise or: `DP_ONOLCK', which means it opens a database file without file locking, or `DP_OLCKNB', which means locking is performed without blocking. `DP_OCREAT' can be added to by bitwise or: `DP_OSPARSE', which means it creates a database file as a sparse file. `bnum' specifies the number of elements of the bucket array. If it is not more than 0, the default value is specified. The size of a bucket array is determined on creating, and can not be changed except for by optimization of the database. Suggested size of a bucket array is about from 0.5 to 4 times of the number of all records to store. The return value is the database handle or `NULL' if it is not successful. While connecting as a writer, an exclusive lock is invoked to the database file. While connecting as a reader, a shared lock is invoked to the database file. The thread blocks until the lock is achieved. If `DP_ONOLCK' is used, the application is responsible for exclusion control. .PP The function `dpclose' is used in order to close a database handle. .TP .B int dpclose(DEPOT *depot); `depot' specifies a database handle. If successful, the return value is true, else, it is false. Because the region of a closed handle is released, it becomes impossible to use the handle. Updating a database is assured to be written when the handle is closed. If a writer opens a database but does not close it appropriately, the database will be broken. .PP The function `dpput' is used in order to store a record. .TP .B int dpput(DEPOT *depot, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int dmode); `depot' specifies a database handle connected as a writer. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `vbuf' specifies the pointer to the region of a value. `vsiz' specifies the size of the region of the value. If it is negative, the size is assigned with `strlen(vbuf)'. `dmode' specifies behavior when the key overlaps, by the following values: `DP_DOVER', which means the specified value overwrites the existing one, `DP_DKEEP', which means the existing value is kept, `DP_DCAT', which means the specified value is concatenated at the end of the existing value. If successful, the return value is true, else, it is false. .PP The function `dpout' is used in order to delete a record. .TP .B int dpout(DEPOT *depot, const char *kbuf, int ksiz); `depot' specifies a database handle connected as a writer. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. If successful, the return value is true, else, it is false. false is returned when no record corresponds to the specified key. .PP The function `dpget' is used in order to retrieve a record. .TP .B char *dpget(DEPOT *depot, const char *kbuf, int ksiz, int start, int max, int *sp); `depot' specifies a database handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `start' specifies the offset address of the beginning of the region of the value to be read. `max' specifies the max size to be read. If it is negative, the size to read is unlimited. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the region of the value of the corresponding record, else, it is `NULL'. `NULL' is returned when no record corresponds to the specified key or the size of the value of the corresponding record is less than `start'. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. .PP The function `dpgetwb' is used in order to retrieve a record and write the value into a buffer. .TP .B int dpgetwb(DEPOT *depot, const char *kbuf, int ksiz, int start, int max, char *vbuf); `depot' specifies a database handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `start' specifies the offset address of the beginning of the region of the value to be read. `max' specifies the max size to be read. It shuld be equal to or less than the size of the writing buffer. `vbuf' specifies the pointer to a buffer into which the value of the corresponding record is written. If successful, the return value is the size of the written data, else, it is \-1. \-1 is returned when no record corresponds to the specified key or the size of the value of the corresponding record is less than `start'. Note that no additional zero code is appended at the end of the region of the writing buffer. .PP The function `dpvsiz' is used in order to get the size of the value of a record. .TP .B int dpvsiz(DEPOT *depot, const char *kbuf, int ksiz); `depot' specifies a database handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. If successful, the return value is the size of the value of the corresponding record, else, it is \-1. Because this function does not read the entity of a record, it is faster than `dpget'. .PP The function `dpiterinit' is used in order to initialize the iterator of a database handle. .TP .B int dpiterinit(DEPOT *depot); `depot' specifies a database handle. If successful, the return value is true, else, it is false. The iterator is used in order to access the key of every record stored in a database. .PP The function `dpiternext' is used in order to get the next key of the iterator. .TP .B char *dpiternext(DEPOT *depot, int *sp); `depot' specifies a database handle. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the region of the next key, else, it is `NULL'. `NULL' is returned when no record is to be get out of the iterator. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. It is possible to access every record by iteration of calling this function. However, it is not assured if updating the database is occurred while the iteration. Besides, the order of this traversal access method is arbitrary, so it is not assured that the order of storing matches the one of the traversal access. .PP The function `dpsetalign' is used in order to set alignment of a database handle. .TP .B int dpsetalign(DEPOT *depot, int align); `depot' specifies a database handle connected as a writer. `align' specifies the size of alignment. If successful, the return value is true, else, it is false. If alignment is set to a database, the efficiency of overwriting values is improved. The size of alignment is suggested to be average size of the values of the records to be stored. If alignment is positive, padding whose size is multiple number of the alignment is placed. If alignment is negative, as `vsiz' is the size of a value, the size of padding is calculated with `(vsiz / pow(2, abs(align) \- 1))'. Because alignment setting is not saved in a database, you should specify alignment every opening a database. .PP The function `dpsetfbpsiz' is used in order to set the size of the free block pool of a database handle. .TP .B int dpsetfbpsiz(DEPOT *depot, int size); `depot' specifies a database handle connected as a writer. `size' specifies the size of the free block pool of a database. If successful, the return value is true, else, it is false. The default size of the free block pool is 16. If the size is greater, the space efficiency of overwriting values is improved with the time efficiency sacrificed. .PP The function `dpsync' is used in order to synchronize updating contents with the file and the device. .TP .B int dpsync(DEPOT *depot); `depot' specifies a database handle connected as a writer. If successful, the return value is true, else, it is false. This function is useful when another process uses the connected database file. .PP The function `dpoptimize' is used in order to optimize a database. .TP .B int dpoptimize(DEPOT *depot, int bnum); `depot' specifies a database handle connected as a writer. `bnum' specifies the number of the elements of the bucket array. If it is not more than 0, the default value is specified. If successful, the return value is true, else, it is false. In an alternating succession of deleting and storing with overwrite or concatenate, dispensable regions accumulate. This function is useful to do away with them. .PP The function `dpname' is used in order to get the name of a database. .TP .B char *dpname(DEPOT *depot); `depot' specifies a database handle. If successful, the return value is the pointer to the region of the name of the database, else, it is `NULL'. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. .PP The function `dpfsiz' is used in order to get the size of a database file. .TP .B int dpfsiz(DEPOT *depot); `depot' specifies a database handle. If successful, the return value is the size of the database file, else, it is \-1. .PP The function `dpbnum' is used in order to get the number of the elements of the bucket array. .TP .B int dpbnum(DEPOT *depot); `depot' specifies a database handle. If successful, the return value is the number of the elements of the bucket array, else, it is \-1. .PP The function `dpbusenum' is used in order to get the number of the used elements of the bucket array. .TP .B int dpbusenum(DEPOT *depot); `depot' specifies a database handle. If successful, the return value is the number of the used elements of the bucket array, else, it is \-1. This function is inefficient because it accesses all elements of the bucket array. .PP The function `dprnum' is used in order to get the number of the records stored in a database. .TP .B int dprnum(DEPOT *depot); `depot' specifies a database handle. If successful, the return value is the number of the records stored in the database, else, it is \-1. .PP The function `dpwritable' is used in order to check whether a database handle is a writer or not. .TP .B int dpwritable(DEPOT *depot); `depot' specifies a database handle. The return value is true if the handle is a writer, false if not. .PP The function `dpfatalerror' is used in order to check whether a database has a fatal error or not. .TP .B int dpfatalerror(DEPOT *depot); `depot' specifies a database handle. The return value is true if the database has a fatal error, false if not. .PP The function `dpinode' is used in order to get the inode number of a database file. .TP .B int dpinode(DEPOT *depot); `depot' specifies a database handle. The return value is the inode number of the database file. .PP The function `dpmtime' is used in order to get the last modified time of a database. .TP .B time_t dpmtime(DEPOT *depot); `depot' specifies a database handle. The return value is the last modified time of the database. .PP The function `dpfdesc' is used in order to get the file descriptor of a database file. .TP .B int dpfdesc(DEPOT *depot); `depot' specifies a database handle. The return value is the file descriptor of the database file. Handling the file descriptor of a database file directly is not suggested. .PP The function `dpremove' is used in order to remove a database file. .TP .B int dpremove(const char *name); `name' specifies the name of a database file. If successful, the return value is true, else, it is false. .PP The function `dprepair' is used in order to repair a broken database file. .TP .B int dprepair(const char *name); `name' specifies the name of a database file. If successful, the return value is true, else, it is false. There is no guarantee that all records in a repaired database file correspond to the original or expected state. .PP The function `dpexportdb' is used in order to dump all records as endian independent data. .TP .B int dpexportdb(DEPOT *depot, const char *name); `depot' specifies a database handle. `name' specifies the name of an output file. If successful, the return value is true, else, it is false. .PP The function `dpimportdb' is used in order to load all records from endian independent data. .TP .B int dpimportdb(DEPOT *depot, const char *name); `depot' specifies a database handle connected as a writer. The database of the handle must be empty. `name' specifies the name of an input file. If successful, the return value is true, else, it is false. .PP The function `dpsnaffle' is used in order to retrieve a record directly from a database file. .TP .B char *dpsnaffle(const char *name, const char *kbuf, int ksiz, int *sp); `name' specifies the name of a database file. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the region of the value of the corresponding record, else, it is `NULL'. `NULL' is returned when no record corresponds to the specified key. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. Although this function can be used even while the database file is locked by another process, it is not assured that recent updated is reflected. .PP The function `dpinnerhash' is a hash function used inside Depot. .TP .B int dpinnerhash(const char *kbuf, int ksiz); `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. The return value is the hash value of 31 bits length computed from the key. This function is useful when an application calculates the state of the inside bucket array. .PP The function `dpouterhash' is a hash function which is independent from the hash functions used inside Depot. .TP .B int dpouterhash(const char *kbuf, int ksiz); `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. The return value is the hash value of 31 bits length computed from the key. This function is useful when an application uses its own hash algorithm outside Depot. .PP The function `dpprimenum' is used in order to get a natural prime number not less than a number. .TP .B int dpprimenum(int num); `num' specified a natural number. The return value is a natural prime number not less than the specified number. This function is useful when an application determines the size of a bucket array of its own hash algorithm. .PP If QDBM was built with POSIX thread enabled, the global variable `dpecode' is treated as thread specific data, and functions of Depot are reentrant. In that case, they are thread\-safe as long as a handle is not accessed by threads at the same time, on the assumption that `errno', `malloc', and so on are thread\-safe. .SH SEE ALSO .PP .BR qdbm (3), .BR curia (3), .BR relic (3), .BR hovel (3), .BR cabin (3), .BR villa (3), .BR odeum (3), .BR ndbm (3), .BR gdbm (3) qdbm-1.8.78/man/hvtest.10000644000175000017500000000202711426314216013717 0ustar mikiomikio.TH HVTEST 1 "2005-06-01" "Man Page" "Quick Database Manager" .SH NAME hvtest \- test cases for QDBM Hovel .SH SYNOPSIS .PP .B hvtest write .RI "[-qdbm] [-s] " name " " rnum .br .B hvtest read .RI "[-qdbm] " name " " rnum .SH DESCRIPTION .PP The command `hvtest' is a utility for facility test and performance test. Check a database generated by the command or measure the execution time of the command. This command is used in the following format. `name' specifies a database name. `rnum' specifies the number of records. .PP .TP .B hvtest write [-qdbm] [-s] name rnum Store records with keys of 8 bytes. They changes as `00000001', `00000002'... .TP .B hvtest read [-qdbm] name rnum Retrieve records of the database above. .PP Options feature the following. .PP .RS .B -qdbm : use `gdbm_open2' and open the handle as Curia. .br .B -s : make the file sparse. .RE .PP This command returns 0 on success, another on failure. .SH SEE ALSO .PP .BR qdbm (3), .BR hovel (3) .SH AUTHOR QDBM was written by Mikio Hirabayashi . qdbm-1.8.78/man/cabin.30000644000175000017500000021167010573416637013502 0ustar mikiomikio.TH CABIN 3 "2004-04-22" "Man Page" "Quick Database Manager" .SH NAME Cabin \- the utility API of QDBM .SH SYNOPSIS .PP .B #include .br .B #include .PP .B extern void (*cbfatalfunc)(const char *message); .PP .B void *cbmalloc(size_t size); .PP .B void *cbrealloc(void *ptr, size_t size); .PP .B char *cbmemdup(const char *ptr, int size); .PP .B void cbfree(void *ptr); .PP .B void cbglobalgc(void *ptr, void (*func)(void *)); .PP .B void cbggcsweep(void); .PP .B int cbvmemavail(size_t size); .PP .B void cbisort(void *base, int nmemb, int size, int(*compar)(const void *, const void *)); .PP .B void cbssort(void *base, int nmemb, int size, int(*compar)(const void *, const void *)); .PP .B void cbhsort(void *base, int nmemb, int size, int(*compar)(const void *, const void *)); .PP .B void cbqsort(void *base, int nmemb, int size, int(*compar)(const void *, const void *)); .PP .B int cbstricmp(const char *astr, const char *bstr); .PP .B int cbstrfwmatch(const char *str, const char *key); .PP .B int cbstrfwimatch(const char *str, const char *key); .PP .B int cbstrbwmatch(const char *str, const char *key); .PP .B int cbstrbwimatch(const char *str, const char *key); .PP .B char *cbstrstrkmp(const char *haystack, const char *needle); .PP .B char *cbstrstrbm(const char *haystack, const char *needle); .PP .B char *cbstrtoupper(char *str); .PP .B char *cbstrtolower(char *str); .PP .B char *cbstrtrim(char *str); .PP .B char *cbstrsqzspc(char *str); .PP .B int cbstrcountutf(const char *str); .PP .B char *cbstrcututf(char *str, int num); .PP .B CBDATUM *cbdatumopen(const char *ptr, int size); .PP .B CBDATUM *cbdatumdup(const CBDATUM *datum); .PP .B void cbdatumclose(CBDATUM *datum); .PP .B void cbdatumcat(CBDATUM *datum, const char *ptr, int size); .PP .B const char *cbdatumptr(const CBDATUM *datum); .PP .B int cbdatumsize(const CBDATUM *datum); .PP .B void cbdatumsetsize(CBDATUM *datum, int size); .PP .B void cbdatumprintf(CBDATUM *datum, const char *format, ...); .PP .B char *cbdatumtomalloc(CBDATUM *datum, int *sp); .PP .B CBLIST *cblistopen(void); .PP .B CBLIST *cblistdup(const CBLIST *list); .PP .B void cblistclose(CBLIST *list); .PP .B int cblistnum(const CBLIST *list); .PP .B const char *cblistval(const CBLIST *list, int index, int *sp); .PP .B void cblistpush(CBLIST *list, const char *ptr, int size); .PP .B char *cblistpop(CBLIST *list, int *sp); .PP .B void cblistunshift(CBLIST *list, const char *ptr, int size); .PP .B char *cblistshift(CBLIST *list, int *sp); .PP .B void cblistinsert(CBLIST *list, int index, const char *ptr, int size); .PP .B char *cblistremove(CBLIST *list, int index, int *sp); .PP .B void cblistover(CBLIST *list, int index, const char *ptr, int size); .PP .B void cblistsort(CBLIST *list); .PP .B int cblistlsearch(const CBLIST *list, const char *ptr, int size); .PP .B int cblistbsearch(const CBLIST *list, const char *ptr, int size); .PP .B char *cblistdump(const CBLIST *list, int *sp); .PP .B CBLIST *cblistload(const char *ptr, int size); .PP .B CBMAP *cbmapopen(void); .PP .B CBMAP *cbmapdup(CBMAP *map); .PP .B void cbmapclose(CBMAP *map); .PP .B int cbmapput(CBMAP *map, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int over); .PP .B void cbmapputcat(CBMAP *map, const char *kbuf, int ksiz, const char *vbuf, int vsiz); .PP .B int cbmapout(CBMAP *map, const char *kbuf, int ksiz); .PP .B const char *cbmapget(const CBMAP *map, const char *kbuf, int ksiz, int *sp); .PP .B int cbmapmove(CBMAP *map, const char *kbuf, int ksiz, int head); .PP .B void cbmapiterinit(CBMAP *map); .PP .B const char *cbmapiternext(CBMAP *map, int *sp); .PP .B const char *cbmapiterval(const char *kbuf, int *sp); .PP .B int cbmaprnum(const CBMAP *map); .PP .B CBLIST *cbmapkeys(CBMAP *map); .PP .B CBLIST *cbmapvals(CBMAP *map); .PP .B char *cbmapdump(const CBMAP *map, int *sp); .PP .B CBMAP *cbmapload(const char *ptr, int size); .PP .B char *cbmaploadone(const char *ptr, int size, const char *kbuf, int ksiz, int *sp); .PP .B CBHEAP *cbheapopen(int size, int max, int(*compar)(const void *, const void *)); .PP .B CBHEAP *cbheapdup(CBHEAP *heap); .PP .B void cbheapclose(CBHEAP *heap); .PP .B int cbheapnum(CBHEAP *heap); .PP .B int cbheapinsert(CBHEAP *heap, const void *ptr); .PP .B void *cbheapval(CBHEAP *heap, int index); .PP .B void *cbheaptomalloc(CBHEAP *heap, int *np); .PP .B char *cbsprintf(const char *format, ...); .PP .B char *cbreplace(const char *str, CBMAP *pairs); .PP .B CBLIST *cbsplit(const char *ptr, int size, const char *delim); .PP .B char *cbreadfile(const char *name, int *sp); .PP .B int cbwritefile(const char *name, const char *ptr, int size); .PP .B CBLIST *cbreadlines(const char *name); .PP .B CBLIST *cbdirlist(const char *name); .PP .B int cbfilestat(const char *name, int *isdirp, int *sizep, time_t *mtimep); .PP .B int cbremove(const char *name); .PP .B CBMAP *cburlbreak(const char *str); .PP .B char *cburlresolve(const char *base, const char *target); .PP .B char *cburlencode(const char *ptr, int size); .PP .B char *cburldecode(const char *str, int *sp); .PP .B char *cbbaseencode(const char *ptr, int size); .PP .B char *cbbasedecode(const char *str, int *sp); .PP .B char *cbquoteencode(const char *ptr, int size); .PP .B char *cbquotedecode(const char *str, int *sp); .PP .B char *cbmimebreak(const char *ptr, int size, CBMAP *attrs, int *sp); .PP .B CBLIST *cbmimeparts(const char *ptr, int size, const char *boundary); .PP .B char *cbmimeencode(const char *str, const char *encname, int base); .PP .B char *cbmimedecode(const char *str, char *enp); .PP .B CBLIST *cbcsvrows(const char *str); .PP .B CBLIST *cbcsvcells(const char *str); .PP .B char *cbcsvescape(const char *str); .PP .B char *cbcsvunescape(const char *str); .PP .B CBLIST *cbxmlbreak(const char *str, int cr); .PP .B CBMAP *cbxmlattrs(const char *str); .PP .B char *cbxmlescape(const char *str); .PP .B char *cbxmlunescape(const char *str); .PP .B char *cbdeflate(const char *ptr, int size, int *sp); .PP .B char *cbinflate(const char *ptr, int size, int *sp); .PP .B char *cbgzencode(const char *ptr, int size, int *sp); .PP .B char *cbgzdecode(const char *ptr, int size, int *sp); .PP .B unsigned int cbgetcrc(const char *ptr, int size); .P .B char *cblzoencode(const char *ptr, int size, int *sp); .PP .B char *cblzodecode(const char *ptr, int size, int *sp); .PP .B char *cbbzencode(const char *ptr, int size, int *sp); .PP .B char *cbbzdecode(const char *ptr, int size, int *sp); .PP .B char *cbiconv(const char *ptr, int size, const char *icode, const char *ocode, int *sp, int *mp); .PP .B const char *cbencname(const char *ptr, int size); .PP .B int cbjetlag(void); .PP .B void cbcalendar(time_t t, int jl, int *yearp, int *monp, int *dayp, int *hourp, int *minp, int *secp); .PP .B int cbdayofweek(int year, int mon, int day); .PP .B char *cbdatestrwww(time_t t, int jl); .PP .B char *cbdatestrhttp(time_t t, int jl); .PP .B time_t cbstrmktime(const char *str); .PP .B void cbproctime(double *usrp, double *sysp); .PP .B void cbstdiobin(void); .SH DESCRIPTION .PP Cabin is the utility API which provides memory allocating functions, sorting functions, extensible datum, array list, hash map, heap array, and so on for handling records easily on memory. This API features also parsing MIME, CSV, and XML, and features various types of encoding and decoding. .PP In order to use Cabin, you should include `cabin.h' and `stdlib.h' in the source files. Usually, the following description will be near the beginning of a source file. .PP .RS .B #include .br .B #include .RE .PP A pointer to `CBDATUM' is used as a handle of an extensible datum. A datum handle is opened with the function `cbdatumopen' and closed with `cbdatumclose'. A pointer to `CBLIST' is used as a handle of an array list. A list handle is opened with the function `cblistopen' and closed with `cblistclose'. A pointer to `CBMAP' is used as a handle of a hash map. A map handle is opened with the function `cbmapopen' and closed with `cbmapclose'. A pointer to `CBHEAP' is used as a handle of a heap array. A heap handle is opened with the function `cbheapopen' and closed with `cbheapclose'. You should not refer directly to any member of each handles. .PP The external variable `cbfatalfunc' is the pointer to call back function for handling a fatal error. .TP .B extern void (*cbfatalfunc)(const char *message); The argument specifies the error message. The initial value of this variable is `NULL'. If the value is `NULL', the default function is called when a fatal error occurs. A fatal error occurs when memory allocation is failed. .PP The function `cbmalloc' is used in order to allocate a region on memory. .TP .B void *cbmalloc(size_t size); `size' specifies the size of the region. The return value is the pointer to the allocated region. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. .PP The function `cbrealloc' is used in order to re\-allocate a region on memory. .TP .B void *cbrealloc(void *ptr, size_t size); `ptr' specifies the pointer to a region. `size' specifies the size of the region. The return value is the pointer to the re\-allocated region. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. .PP The function `cbmemdup' is used in order to duplicate a region on memory. .TP .B char *cbmemdup(const char *ptr, int size); `ptr' specifies the pointer to a region. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. The return value is the pointer to the allocated region of the duplicate. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. .PP The function `cbfree' is used in order to free a region on memory. .TP .B void cbfree(void *ptr); `ptr' specifies the pointer to a region. If it is `NULL', this function has no effect. Although this function is just a wrapper of `free' call, this is useful in applications using another package of the `malloc' series. .PP The function `cbglobalgc' is used in order to register the pointer or handle of an object to the global garbage collector. .TP .B void cbglobalgc(void *ptr, void (*func)(void *)); `ptr' specifies the pointer or handle of an object. `func' specifies the pointer to a function to release resources of the object. Its argument is the pointer or handle of the object to release. This function assures that resources of an object are released when the process exits normally by returning from the `main' function or calling the `exit' function. .PP The function `cbggcsweep' is used in order to exercise the global garbage collector explicitly. .TP .B void cbggcsweep(void); Note that you should not use objects registered to the global garbage collector any longer after calling this function. Because the global garbage collector is initialized and you can register new objects into it. .PP The function `cbvmemavail' is used in order to check availability of allocation of the virtual memory. .TP .B int cbvmemavail(size_t size); `size' specifies the size of region to be allocated newly. The return value is true if allocation should be success, or false if not. .PP The function `cbisort' is used in order to sort an array using insert sort. .TP .B void cbisort(void *base, int nmemb, int size, int(*compar)(const void *, const void *)); `base' specifies the pointer to an array. `nmemb' specifies the number of elements of the array. `size' specifies the size of each element. `compar' specifies the pointer to comparing function. The two arguments specify the pointers of elements. The comparing function should returns positive if the former is big, negative if the latter is big, 0 if both are equal. Insert sort is useful only if most elements have been sorted already. .PP The function `cbssort' is used in order to sort an array using shell sort. .TP .B void cbssort(void *base, int nmemb, int size, int(*compar)(const void *, const void *)); `base' specifies the pointer to an array. `nmemb' specifies the number of elements of the array. `size' specifies the size of each element. `compar' specifies the pointer to comparing function. The two arguments specify the pointers of elements. The comparing function should returns positive if the former is big, negative if the latter is big, 0 if both are equal. If most elements have been sorted, shell sort may be faster than heap sort or quick sort. .PP The function `cbhsort' is used in order to sort an array using heap sort. .TP .B void cbhsort(void *base, int nmemb, int size, int(*compar)(const void *, const void *)); `base' specifies the pointer to an array. `nmemb' specifies the number of elements of the array. `size' specifies the size of each element. `compar' specifies the pointer to comparing function. The two arguments specify the pointers of elements. The comparing function should returns positive if the former is big, negative if the latter is big, 0 if both are equal. Although heap sort is robust against bias of input, quick sort is faster in most cases. .PP The function `cbqsort' is used in order to sort an array using quick sort. .TP .B void cbqsort(void *base, int nmemb, int size, int(*compar)(const void *, const void *)); `base' specifies the pointer to an array. `nmemb' specifies the number of elements of the array. `size' specifies the size of each element. `compar' specifies the pointer to comparing function. The two arguments specify the pointers of elements. The comparing function should returns positive if the former is big, negative if the latter is big, 0 if both are equal. Being sensitive to bias of input, quick sort is the fastest sorting algorithm. .PP The function `cbstricmp' is used in order to compare two strings with case insensitive evaluation. .TP .B int cbstricmp(const char *astr, const char *bstr); `astr' specifies the pointer of one string. `astr' specifies the pointer of the other string. The return value is positive if the former is big, negative if the latter is big, 0 if both are equivalent. Upper cases and lower cases of alphabets in ASCII code are not distinguished. .PP The function `cbstrfwmatch' is used in order to check whether a string begins with a key. .TP .B int cbstrfwmatch(const char *str, const char *key); `str' specifies the pointer of a target string. `key' specifies the pointer of a forward matching key string. The return value is true if the target string begins with the key, else, it is false. .PP The function `cbstrfwimatch' is used in order to check whether a string begins with a key, with case insensitive evaluation. .TP .B int cbstrfwimatch(const char *str, const char *key); `str' specifies the pointer of a target string. `key' specifies the pointer of a forward matching key string. The return value is true if the target string begins with the key, else, it is false. Upper cases and lower cases of alphabets in ASCII code are not distinguished. .PP The function `cbstrbwmatch' is used in order to check whether a string ends with a key. .TP .B int cbstrbwmatch(const char *str, const char *key); `str' specifies the pointer of a target string. `key' specifies the pointer of a backward matching key string. The return value is true if the target string ends with the key, else, it is false. .PP The function `cbstrbwimatch' is used in order to check whether a string ends with a key, with case insensitive evaluation. .TP .B int cbstrbwimatch(const char *str, const char *key); `str' specifies the pointer of a target string. `key' specifies the pointer of a backward matching key string. The return value is true if the target string ends with the key, else, it is false. Upper cases and lower cases of alphabets in ASCII code are not distinguished. .PP The function `cbstrstrkmp' is used in order to locate a substring in a string using KMP method. .TP .B char *cbstrstrkmp(const char *haystack, const char *needle); `haystack' specifies the pointer of a target string. `needle' specifies the pointer of a substring to be found. The return value is the pointer to the beginning of the substring or `NULL' if the substring is not found. In most cases, `strstr' as a built\-in function of the compiler is faster than this function. .PP The function `cbstrstrkmp' is used in order to locate a substring in a string using BM method. .TP .B char *cbstrstrbm(const char *haystack, const char *needle); `haystack' specifies the pointer of a target string. `needle' specifies the pointer of a substring to be found. The return value is the pointer to the beginning of the substring or `NULL' if the substring is not found. In most cases, `strstr' as a built\-in function of the compiler is faster than this function. .PP The function `cbstrtoupper' is used in order to convert the letters of a string to upper case. .TP .B char *cbstrtoupper(char *str); `str' specifies the pointer of a string to convert. The return value is the pointer to the string. .PP The function `cbstrtolower' is used in order to convert the letters of a string to lower case. .TP .B char *cbstrtolower(char *str); `str' specifies the pointer of a string to convert. The return value is the pointer to the string. .PP The function `cbstrtrim' is used in order to cut space characters at head or tail of a string. .TP .B char *cbstrtrim(char *str); `str' specifies the pointer of a string to convert. The return value is the pointer to the string. .PP The function `cbstrsqzspc' is used in order to squeeze space characters in a string and trim it. .TP .B char *cbstrsqzspc(char *str); `str' specifies the pointer of a string to convert. The return value is the pointer to the string. .PP The function `cbstrcountutf' is used in order to count the number of characters in a string of UTF\-8. .TP .B int cbstrcountutf(const char *str); `str' specifies the pointer of a string of UTF\-8. The return value is the number of characters in the string. .PP The function `cbstrcututf' is used in order to cut a string of UTF\-8 at the specified number of characters. .TP .B char *cbstrcututf(char *str, int num); `str' specifies the pointer of a string of UTF\-8. `num' specifies the number of characters to be kept. The return value is the pointer to the string. .PP The function `cbdatumopen' is used in order to get a datum handle. .TP .B CBDATUM *cbdatumopen(const char *ptr, int size); `ptr' specifies the pointer to the region of the initial content. If it is `NULL', an empty datum is created. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. The return value is a datum handle. .PP The function `cbdatumdup' is used in order to copy a datum. .TP .B CBDATUM *cbdatumdup(const CBDATUM *datum); `datum' specifies a datum handle. The return value is a new datum handle. .PP The function `cbdatumclose' is used in order to free a datum handle. .TP .B void cbdatumclose(CBDATUM *datum); `datum' specifies a datum handle. Because the region of a closed handle is released, it becomes impossible to use the handle. .PP The function `cbdatumcat' is used in order to concatenate a datum and a region. .TP .B void cbdatumcat(CBDATUM *datum, const char *ptr, int size); `datum' specifies a datum handle. `ptr' specifies the pointer to the region to be appended. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. .PP The function `cbdatumptr' is used in order to get the pointer of the region of a datum. .TP .B const char *cbdatumptr(const CBDATUM *datum); `datum' specifies a datum handle. The return value is the pointer of the region of a datum. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. .PP The function `cbdatumsize' is used in order to get the size of the region of a datum. .TP .B int cbdatumsize(const CBDATUM *datum); `datum' specifies a datum handle. The return value is the size of the region of a datum. .PP The function `cbdatumsetsize' is used in order to change the size of the region of a datum. .TP .B void cbdatumsetsize(CBDATUM *datum, int size); `datum' specifies a datum handle. `size' specifies the new size of the region. If the new size is bigger than the one of old, the surplus region is filled with zero codes. .PP The function `cbdatumprintf' is used in order to perform formatted output into a datum. .TP .B void cbdatumprintf(CBDATUM *datum, const char *format, ...); `format' specifies a printf-like format string. The conversion character `%' can be used with such flag characters as `s', `d', `o', `u', `x', `X', `c', `e', `E', `f', `g', `G', `@', `?', `:', `%'. `@' works as with `s' but escapes meta characters of XML. `?' works as with `s' but escapes meta characters of URL. `:' works as with `s' but performs MIME encoding as UTF-8. The other conversion character work as with each original. .PP The function `cbdatumtomalloc' is used in order to convert a datum to an allocated region. .TP .B char *cbdatumtomalloc(CBDATUM *datum, int *sp); `datum' specifies a datum handle. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. The return value is the pointer to the region of the datum. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. Because the region of the original datum is released, it should not be released again. .PP The function `cblistopen' is used in order to get a list handle. .TP .B CBLIST *cblistopen(void); The return value is a list handle. .PP The function `cblistdup' is used in order to copy a list. .TP .B CBLIST *cblistdup(const CBLIST *list); `list' specifies a list handle. The return value is a new list handle. .PP The function `cblistclose' is used in order to close a list handle. .TP .B void cblistclose(CBLIST *list); `list' specifies a list handle. Because the region of a closed handle is released, it becomes impossible to use the handle. .PP The function `cblistnum' is used in order to get the number of elements of a list. .TP .B int cblistnum(const CBLIST *list); `list' specifies a list handle. The return value is the number of elements of the list. .PP The function `cblistval' is used in order to get the pointer to the region of an element of a list. .TP .B const char *cblistval(const CBLIST *list, int index, int *sp); `list' specifies a list handle. `index' specifies the index of an element. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. The return value is the pointer to the region of the element. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. If `index' is equal to or more than the number of elements, the return value is `NULL'. .PP The function `cblistpush' is used in order to add an element at the end of a list. .TP .B void cblistpush(CBLIST *list, const char *ptr, int size); `list' specifies a list handle. `ptr' specifies the pointer to the region of an element. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. .PP The function `cblistpop' is used in order to remove an element of the end of a list. .TP .B char *cblistpop(CBLIST *list, int *sp); `list' specifies a list handle. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. The return value is the pointer to the region of the value. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. If the list is empty, the return value is `NULL'. .PP The function `cblistunshift' is used in order to add an element at the top of a list. .TP .B void cblistunshift(CBLIST *list, const char *ptr, int size); `list' specifies a list handle. `ptr' specifies the pointer to the region of an element. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. .PP The function `cblistshift' is used in order to remove an element of the top of a list. .TP .B char *cblistshift(CBLIST *list, int *sp); `list' specifies a list handle. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. The return value is the pointer to the region of the value. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. If the list is empty, the return value is `NULL'. .PP The function `cblistinsert' is used in order to add an element at the specified location of a list. .TP .B void cblistinsert(CBLIST *list, int index, const char *ptr, int size); `list' specifies a list handle. `index' specifies the index of an element. `ptr' specifies the pointer to the region of the element. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. .PP The function `cblistremove' is used in order to remove an element at the specified location of a list. .TP .B char *cblistremove(CBLIST *list, int index, int *sp); `list' specifies a list handle. `index' specifies the index of an element. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. The return value is the pointer to the region of the value. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. If `index' is equal to or more than the number of elements, no element is removed and the return value is `NULL'. .PP The function `cblistover' is used in order to overwrite an element at the specified location of a list. .TP .B void cblistover(CBLIST *list, int index, const char *ptr, int size); `list' specifies a list handle. `index' specifies the index of an element. `ptr' specifies the pointer to the region of the new content. `size' specifies the size of the new content. If it is negative, the size is assigned with `strlen(ptr)'. If `index' is equal to or more than the number of elements, this function has no effect. .PP The function `cblistsort' is used in order to sort elements of a list in lexical order. .TP .B void cblistsort(CBLIST *list); `list' specifies a list handle. Quick sort is used for sorting. .PP The function `cblistlsearch' is used in order to search a list for an element using liner search. .TP .B int cblistlsearch(const CBLIST *list, const char *ptr, int size); `list' specifies a list handle. `ptr' specifies the pointer to the region of a key. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. The return value is the index of a corresponding element or \-1 if there is no corresponding element. If two or more elements corresponds, the former returns. .PP The function `cblistbsearch' is used in order to search a list for an element using binary search. .TP .B int cblistbsearch(const CBLIST *list, const char *ptr, int size); `list' specifies a list handle. It should be sorted in lexical order. `ptr' specifies the pointer to the region of a key. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. The return value is the index of a corresponding element or \-1 if there is no corresponding element. If two or more elements corresponds, which returns is not defined. .PP The function `cblistdump' is used in order to serialize a list into a byte array. .TP .B char *cblistdump(const CBLIST *list, int *sp); `list' specifies a list handle. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. The return value is the pointer to the region of the result serial region. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. .PP The function `cblistload' is used in order to redintegrate a serialized list. .TP .B CBLIST *cblistload(const char *ptr, int size); `ptr' specifies the pointer to a byte array. `size' specifies the size of the region. The return value is a new list handle. .PP The function `cbmapopen' is used in order to get a map handle. .TP .B CBMAP *cbmapopen(void); The return value is a map handle. .PP The function `cbmapdup' is used in order to copy a map. .TP .B CBMAP *cbmapdup(CBMAP *map); `map' specifies a map handle. The return value is a new map handle. The iterator of the source map is initialized. .PP The function `cbmapclose' is used in order to close a map handle. .TP .B void cbmapclose(CBMAP *map); `map' specifies a map handle. Because the region of a closed handle is released, it becomes impossible to use the handle. .PP The function `cbmapput' is used in order to store a record into a map. .TP .B int cbmapput(CBMAP *map, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int over); `map' specifies a map handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `vbuf' specifies the pointer to the region of a value. `vsiz' specifies the size of the region of the value. If it is negative, the size is assigned with `strlen(vbuf)'. `over' specifies whether the value of the duplicated record is overwritten or not. If `over' is false and the key is duplicated, the return value is false, else, it is true. .PP The function `cbmapputcat' is used in order to concatenate a value at the end of the value of the existing record. .TP .B void cbmapputcat(CBMAP *map, const char *kbuf, int ksiz, const char *vbuf, int vsiz); `map' specifies a map handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `vbuf' specifies the pointer to the region of a value. `vsiz' specifies the size of the region of the value. If it is negative, the size is assigned with `strlen(vbuf)'. If there is no corresponding record, a new record is created. .PP The function `cbmapout' is used in order to delete a record in a map. .TP .B int cbmapout(CBMAP *map, const char *kbuf, int ksiz); `map' specifies a map handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. If successful, the return value is true. False is returned when no record corresponds to the specified key. .PP The function `cbmapget' is used in order to retrieve a record in a map. .TP .B const char *cbmapget(const CBMAP *map, const char *kbuf, int ksiz, int *sp); `map' specifies a map handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the region of the value of the corresponding record. `NULL' is returned when no record corresponds. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. .PP The function `cbmapmove' is used in order to move a record to the edge of a map. .TP .B int cbmapmove(CBMAP *map, const char *kbuf, int ksiz, int head); `map' specifies a map handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `head' specifies the destination which is head if it is true or tail if else. If successful, the return value is true. False is returned when no record corresponds to the specified key. .PP The function `cbmapiterinit' is used in order to initialize the iterator of a map. .TP .B void cbmapiterinit(CBMAP *map); `map' specifies a map handle. The iterator is used in order to access the key of every record stored in a map. .PP The function `cbmapiternext' is used in order to get the next key of the iterator of a map. .TP .B const char *cbmapiternext(CBMAP *map, int *sp); `map' specifies a map handle. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the region of the next key, else, it is `NULL'. `NULL' is returned when no record is to be get out of the iterator. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. The order of iteration is assured to be the same of the one of storing. .PP The function `cbmapiterval' is used in order to get the value binded to the key fetched from the iterator of a map. .TP .B const char *cbmapiterval(const char *kbuf, int *sp); `kbuf' specifies the pointer to the region of a iteration key. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. The return value is the pointer to the region of the value of the corresponding record. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. .PP The function `cbmaprnum' is used in order to get the number of the records stored in a map. .TP .B int cbmaprnum(const CBMAP *map); `map' specifies a map handle. The return value is the number of the records stored in the map. .PP The function `cbmapkeys' is used in order to get the list handle contains all keys in a map. .TP .B CBLIST *cbmapkeys(CBMAP *map); `map' specifies a map handle. The return value is the list handle contains all keys in the map. Because the handle of the return value is opened with the function `cblistopen', it should be closed with the function `cblistclose' if it is no longer in use. .PP The function `cbmapvals' is used in order to get the list handle contains all values in a map. .TP .B CBLIST *cbmapvals(CBMAP *map); `map' specifies a map handle. The return value is the list handle contains all values in the map. Because the handle of the return value is opened with the function `cblistopen', it should be closed with the function `cblistclose' if it is no longer in use. .PP The function `cbmapdump' is used in order to serialize a map into a byte array. .TP .B char *cbmapdump(const CBMAP *map, int *sp); `map' specifies a map handle. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. The return value is the pointer to the region of the result serial region. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. .PP The function `cbmapload' is used in order to redintegrate a serialized map. .TP .B CBMAP *cbmapload(const char *ptr, int size); `ptr' specifies the pointer to a byte array. `size' specifies the size of the region. The return value is a new map handle. .PP The function `cbmaploadone' is used in order to extract a record from a serialized map. .TP .B char *cbmaploadone(const char *ptr, int size, const char *kbuf, int ksiz, int *sp); `ptr' specifies the pointer to a byte array. `size' specifies the size of the region. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the region of the value of the corresponding record. `NULL' is returned when no record corresponds. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. .PP The function `cbheapopen' is used in order to get a heap handle. .TP .B CBHEAP *cbheapopen(int size, int max, int(*compar)(const void *, const void *)); `size' specifies the size of each record. `max' specifies the maximum number of records in the heap. `compar' specifies the pointer to comparing function. The two arguments specify the pointers of records. The comparing function should returns positive if the former is big, negative if the latter is big, 0 if both are equal. The return value is a heap handle. .PP The function `cbheapdup' is used in order to copy a heap. .TP .B CBHEAP *cbheapdup(CBHEAP *heap); `heap' specifies a heap handle. The return value is a new heap handle. .PP The function `cbheapclose' is used in order to close a heap handle. .TP .B void cbheapclose(CBHEAP *heap); `heap' specifies a heap handle. Because the region of a closed handle is released, it becomes impossible to use the handle. .PP The function `cbheapnum' is used in order to get the number of the records stored in a heap. .TP .B int cbheapnum(CBHEAP *heap); `heap' specifies a heap handle. The return value is the number of the records stored in the heap. .PP The function `cbheapinsert' is used in order to insert a record into a heap. .TP .B int cbheapinsert(CBHEAP *heap, const void *ptr); `heap' specifies a heap handle. `ptr' specifies the pointer to the region of a record. The return value is true if the record is added, else false. If the new record is bigger than the biggest existing regord, the new record is not added. If the new record is added and the number of records exceeds the maximum number, the biggest existing record is removed. .PP The function `cbheapval' is used in order to get the pointer to the region of a record in a heap. .TP .B void *cbheapval(CBHEAP *heap, int index); `heap' specifies a heap handle. `index' specifies the index of a record. The return value is the pointer to the region of the record. If `index' is equal to or more than the number of records, the return value is `NULL'. Note that records are organized by the nagative order the comparing function. .PP The function `cbheaptomalloc' is used in order to convert a heap to an allocated region. .TP .B void *cbheaptomalloc(CBHEAP *heap, int *np); `heap' specifies a heap handle. `np' specifies the pointer to a variable to which the number of records of the return value is assigned. If it is `NULL', it is not used. The return value is the pointer to the region of the heap. Records are sorted. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. Because the region of the original heap is released, it should not be released again. .PP The function `cbsprintf' is used in order to allocate a formatted string on memory. .TP .B char *cbsprintf(const char *format, ...); `format' specifies a printf\-like format string. The conversion character `%' can be used with such flag characters as `d', `o', `u', `x', `X', `e', `E', `f', `g', `G', `c', `s', and `%'. Specifiers of the field length and the precision can be put between the conversion characters and the flag characters. The specifiers consist of decimal characters, `.', `+', `\-', and the space character. The other arguments are used according to the format string. The return value is the pointer to the allocated region of the result string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. .PP The function `cbreplace' is used in order to replace some patterns in a string. .TP .B char *cbreplace(const char *str, CBMAP *pairs); `str' specifies the pointer to a source string. `pairs' specifies the handle of a map composed of pairs of replacement. The key of each pair specifies a pattern before replacement and its value specifies the pattern after replacement. The return value is the pointer to the allocated region of the result string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. .PP The function `cbsplit' is used in order to make a list by splitting a serial datum. .TP .B CBLIST *cbsplit(const char *ptr, int size, const char *delim); `ptr' specifies the pointer to the region of the source content. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. `delim' specifies a string containing delimiting characters. If it is `NULL', zero code is used as a delimiter. The return value is a list handle. If two delimiters are successive, it is assumed that an empty element is between the two. Because the handle of the return value is opened with the function `cblistopen', it should be closed with the function `cblistclose'. .PP The function `cbreadfile' is used in order to read whole data of a file. .TP .B char *cbreadfile(const char *name, int *sp); `name' specifies the name of a file. If it is `NULL', the standard input is specified. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. The return value is the pointer to the allocated region of the read data. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. .PP The function `cbwritefile' is used in order to write a serial datum into a file. .TP .B int cbwritefile(const char *name, const char *ptr, int size); `name specifies the name of a file. If it is `NULL', the standard output is specified. `ptr' specifies the pointer to the region of the source content. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. If successful, the return value is true, else, it is false. If the file exists, it is overwritten. Else, a new file is created. .PP The function `cbreadlines' is used in order to read every line of a file. .TP .B CBLIST *cbreadlines(const char *name); `name' specifies the name of a file. If it is `NULL', the standard input is specified. The return value is a list handle of the lines if successful, else it is NULL. Line separators are cut out. Because the handle of the return value is opened with the function `cblistopen', it should be closed with the function `cblistclose' if it is no longer in use. .PP The function `cbdirlist' is used in order to read names of files in a directory. .TP .B CBLIST *cbdirlist(const char *name); `name' specifies the name of a directory. The return value is a list handle of names if successful, else it is NULL. Because the handle of the return value is opened with the function `cblistopen', it should be closed with the function `cblistclose' if it is no longer in use. .PP The function `cbfilestat' is used in order to get the status of a file or a directory. .TP .B int cbfilestat(const char *name, int *isdirp, int *sizep, time_t *mtimep); `name' specifies the name of a file or a directory. `dirp' specifies the pointer to a variable to which whether the file is a directory is assigned. If it is `NULL', it is not used. `sizep' specifies the pointer to a variable to which the size of the file is assigned. If it is `NULL', it is not used. `mtimep' specifies the pointer to a variable to which the last modified time of the file is assigned. If it is `NULL', it is not used. If successful, the return value is true, else, false. False is returned when the file does not exist or the permission is denied. .PP The function `cbremove' is used in order to remove a file or a directory and its sub ones recursively. .TP .B int cbremove(const char *name); `name' specifies the name of a file or a directory. If successful, the return value is true, else, false. False is returned when the file does not exist or the permission is denied. .PP The function `cburlbreak' is used in order to break up a URL into elements. .TP .B CBMAP *cburlbreak(const char *str); `str' specifies the pointer to a string of URL. The return value is a map handle. Each key of the map is the name of an element. The key "self" specifies the URL itself. The key "scheme" specifies the scheme. The key "host" specifies the host of the server. The key "port" specifies the port number of the server. The key "authority" specifies the authority information. The key "path" specifies the path of the resource. The key "file" specifies the file name without the directory section. The key "query" specifies the query string. The key "fragment" specifies the fragment string. Supported schema are HTTP, HTTPS, FTP, and FILE. Absolute URL and relative URL are supported. Because the handle of the return value is opened with the function `cbmapopen', it should be closed with the function `cbmapclose' if it is no longer in use. .PP The runction `cburlresolve' is used in order to resolve a relative URL with another absolute URL. .TP .B char *cburlresolve(const char *base, const char *target); `base' specifies an absolute URL of a base location. `target' specifies a URL to be resolved. The return value is a resolved URL. If the target URL is relative, a new URL of relative location from the base location is returned. Else, a copy of the target URL is returned. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. .PP The function `cburlencode' is used in order to encode a serial object with URL encoding. .TP .B char *cburlencode(const char *ptr, int size); `ptr' specifies the pointer to a region. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. The return value is the pointer to the result string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. .PP The function `cburldecode' is used in order to decode a string encoded with URL encoding. .TP .B char *cburldecode(const char *str, int *sp); `str' specifies the pointer to a source string. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. The return value is the pointer to the region of the result. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. .PP The function `cbbaseencode' is used in order to encode a serial object with Base64 encoding. .TP .B char *cbbaseencode(const char *ptr, int size); `ptr' specifies the pointer to a region. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. The return value is the pointer to the result string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. .PP The function `cbbasedecode' is used in order to decode a string encoded with Base64 encoding. .TP .B char *cbbasedecode(const char *str, int *sp); `str' specifies the pointer to a source string. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. The return value is the pointer to the region of the result. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. .PP The function `cbquoteencode' is used in order to encode a serial object with quoted\-printable encoding. .TP .B char *cbquoteencode(const char *ptr, int size); `ptr' specifies the pointer to a region. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. The return value is the pointer to the result string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. .PP The function `cbquotedecode' is used in order to decode a string encoded with quoted\-printable encoding. .TP .B char *cbquotedecode(const char *str, int *sp); `str' specifies the pointer to a source string. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. The return value is the pointer to the region of the result. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. .PP The function `cbmimebreak' is used in order to split a string of MIME into headers and the body. .TP .B char *cbmimebreak(const char *ptr, int size, CBMAP *attrs, int *sp); `ptr' specifies the pointer to the region of MIME data. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. `attrs' specifies a map handle to store attributes. If it is `NULL', it is not used. Each key of the map is an attribute name uncapitalized. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. The return value is the pointer of the body data. If the content type is defined, the attribute map has the key "TYPE" specifying the type. If the character encoding is defined, the key "CHARSET" specifies the encoding name. If the boundary string of multipart is defined, the key "BOUNDARY" specifies the string. If the content disposition is defined, the key "DISPOSITION" specifies the direction. If the file name is defined, the key "FILENAME" specifies the name. If the attribute name is defined, the key "NAME" specifies the name. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. .PP The function `cbmimeparts' is used in order to split multipart data of MIME into its parts. .TP .B CBLIST *cbmimeparts(const char *ptr, int size, const char *boundary); `ptr' specifies the pointer to the region of multipart data of MIME. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. `boundary' specifies the pointer to the region of the boundary string. The return value is a list handle. Each element of the list is the string of a part. Because the handle of the return value is opened with the function `cblistopen', it should be closed with the function `cblistclose' if it is no longer in use. .PP The function `cbmimeencode' is used in order to encode a string with MIME encoding. .TP .B char *cbmimeencode(const char *str, const char *encname, int base); `str' specifies the pointer to a string. `encname' specifies a string of the name of the character encoding. The return value is the pointer to the result string. `base' specifies whether to use Base64 encoding. If it is false, quoted\-printable is used. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. .PP The function `cbmimedecode' is used in order to decode a string encoded with MIME encoding. .TP .B char *cbmimedecode(const char *str, char *enp); `str' specifies the pointer to an encoded string. `enp' specifies the pointer to a region into which the name of encoding is written. If it is `NULL', it is not used. The size of the buffer should be equal to or more than 32 bytes. The return value is the pointer to the result string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. .PP The function `cbcsvrows' is used in order to split a string of CSV into rows. .TP .B CBLIST *cbcsvrows(const char *str); `str' specifies the pointer to the region of an CSV string. The return value is a list handle. Each element of the list is a string of a row. Because the handle of the return value is opened with the function `cblistopen', it should be closed with the function `cblistclose' if it is no longer in use. The character encoding of the input string should be US\-ASCII, UTF\-8, ISO\-8859\-*, EUC\-*, or Shift_JIS. Being compatible with MS\-Excel, these functions for CSV can handle cells including such meta characters as comma, between double quotation marks. .PP The function `cbcsvcells' is used in order to split the string of a row of CSV into cells. .TP .B CBLIST *cbcsvcells(const char *str); `str' specifies the pointer to the region of a row of CSV. The return value is a list handle. Each element of the list is the unescaped string of a cell of the row. Because the handle of the return value is opened with the function `cblistopen', it should be closed with the function `cblistclose' if it is no longer in use. .PP The function `cbcsvescape' is used in order to escape a string with the meta characters of CSV. .TP .B char *cbcsvescape(const char *str); `str' specifies the pointer to the region of a string. The return value is the pointer to the escaped string sanitized of meta characters. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. .PP The function `cbcsvunescape' is used in order to unescape a string with the escaped meta characters of CSV. .TP .B char *cbcsvunescape(const char *str); `str' specifies the pointer to the region of a string with meta characters. The return value is the pointer to the unescaped string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. .PP The function `cbxmlbreak' is used in order to split a string of XML into tags and text sections. .TP .B CBLIST *cbxmlbreak(const char *str, int cr); `str' specifies the pointer to the region of an XML string. `cr' specifies whether to remove comments. The return value is a list handle. Each element of the list is the string of a tag or a text section. Because the handle of the return value is opened with the function `cblistopen', it should be closed with the function `cblistclose' if it is no longer in use. The character encoding of the input string should be US\-ASCII, UTF\-8, ISO\-8859\-*, EUC\-*, or Shift_JIS. Because these functions for XML are not XML parser with validation check, it can handle also HTML and SGML. .PP The function `cbxmlattrs' is used in order to get the map of attributes of an XML tag. .TP .B CBMAP *cbxmlattrs(const char *str); `str' specifies the pointer to the region of a tag string. The return value is a map handle. Each key of the map is the name of an attribute. Each value is unescaped. You can get the name of the tag with the key of an empty string. Because the handle of the return value is opened with the function `cbmapopen', it should be closed with the function `cbmapclose' if it is no longer in use. .PP The function `cbxmlescape' is used in order to escape a string with the meta characters of XML. .TP .B char *cbxmlescape(const char *str); `str' specifies the pointer to the region of a string. The return value is the pointer to the escaped string sanitized of meta characters. This function converts only `&', `<', `>', and `"'. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. .PP The function `cbxmlunescape' is used in order to unescape a string with the entity references of XML. .TP .B char *cbxmlunescape(const char *str); `str' specifies the pointer to the region of a string. The return value is the pointer to the unescaped string. This function restores only `&', `<', `>', and `"'. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. .PP The function `cbdeflate' is used in order to compress a serial object with ZLIB. .TP .B char *cbdeflate(const char *ptr, int size, int *sp); `ptr' specifies the pointer to a region. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If successful, the return value is the pointer to the result object, else, it is `NULL'. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. This function is available only if QDBM was built with ZLIB enabled. .PP The function `cbinflate' is used in order to decompress a serial object compressed with ZLIB. .TP .B char *cbinflate(const char *ptr, int size, int *sp); `ptr' specifies the pointer to a region. `size' specifies the size of the region. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the result object, else, it is `NULL'. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. This function is available only if QDBM was built with ZLIB enabled. .PP The function `cbgzencode' is used in order to compress a serial object with GZIP. .TP .B char *cbgzencode(const char *ptr, int size, int *sp); `ptr' specifies the pointer to a region. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If successful, the return value is the pointer to the result object, else, it is `NULL'. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. This function is available only if QDBM was built with ZLIB enabled. .PP The function `cbgzdecode' is used in order to decompress a serial object compressed with GZIP. .TP .B char *cbgzdecode(const char *ptr, int size, int *sp); `ptr' specifies the pointer to a region. `size' specifies the size of the region. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the result object, else, it is `NULL'. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. This function is available only if QDBM was built with ZLIB enabled. .PP The function `cbgetcrc' is used in order to get the CRC32 checksum of a serial object. .TP .B unsigned int cbgetcrc(const char *ptr, int size); `ptr' specifies the pointer to a region. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. The return value is the CRC32 checksum of the object. This function is available only if QDBM was built with ZLIB enabled. .PP The function `cblzoencode' is used in order to compress a serial object with LZO. .TP .B char *cblzoencode(const char *ptr, int size, int *sp); `ptr' specifies the pointer to a region. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If successful, the return value is the pointer to the result object, else, it is `NULL'. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. This function is available only if QDBM was built with LZO enabled. .PP The function `cblzodecode' is used in order to decompress a serial object compressed with LZO. .TP .B char *cblzodecode(const char *ptr, int size, int *sp); `ptr' specifies the pointer to a region. `size' specifies the size of the region. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the result object, else, it is `NULL'. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. This function is available only if QDBM was built with LZO enabled. .PP The function `cbbzencode' is used in order to compress a serial object with BZIP2. .TP .B char *cbbzencode(const char *ptr, int size, int *sp); `ptr' specifies the pointer to a region. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If successful, the return value is the pointer to the result object, else, it is `NULL'. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. This function is available only if QDBM was built with BZIP2 enabled. .PP The function `cbbzdecode' is used in order to decompress a serial object compressed with BZIP2. .TP .B char *cbbzdecode(const char *ptr, int size, int *sp); `ptr' specifies the pointer to a region. `size' specifies the size of the region. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the result object, else, it is `NULL'. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. This function is available only if QDBM was built with BZIP2 enabled. .PP The function `cbiconv' is used in order to convert the character encoding of a string. .TP .B char *cbiconv(const char *ptr, int size, const char *icode, const char *ocode, int *sp, int *mp); `ptr' specifies the pointer to a region. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. `icode' specifies the name of encoding of the input string. `ocode' specifies the name of encoding of the output string. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. `mp' specifies the pointer to a variable to which the number of missing characters by failure of conversion is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the result object, else, it is `NULL'. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. This function is available only if QDBM was built with ICONV enabled. .PP The function `cbencname' is used in order to detect the encoding of a string automatically. .TP .B const char *cbencname(const char *ptr, int size); `ptr' specifies the pointer to a region. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. The return value is the string of the encoding name of the string. As it stands, US\-ASCII, ISO\-2022\-JP, Shift_JIS, CP932, EUC\-JP, UTF\-8, UTF\-16, UTF\-16BE, and UTF\-16LE are supported. If none of them matches, ISO\-8859\-1 is selected. This function is available only if QDBM was built with ICONV enabled. .PP The function `cbjetlag' is used in order to get the jet lag of the local time in seconds. .TP .B int cbjetlag(void); The return value is the jet lag of the local time in seconds. .PP The function `cbcalendar' is used in order to get the Gregorian calendar of a time. .TP .B void cbcalendar(time_t t, int jl, int *yearp, int *monp, int *dayp, int *hourp, int *minp, int *secp); `t' specifies a source time. If it is negative, the current time is specified. `jl' specifies the jet lag of a location in seconds. `yearp' specifies the pointer to a variable to which the year is assigned. If it is `NULL', it is not used. `monp' specifies the pointer to a variable to which the month is assigned. If it is `NULL', it is not used. 1 means January and 12 means December. `dayp' specifies the pointer to a variable to which the day of the month is assigned. If it is `NULL', it is not used. `hourp' specifies the pointer to a variable to which the hours is assigned. If it is `NULL', it is not used. `minp' specifies the pointer to a variable to which the minutes is assigned. If it is `NULL', it is not used. `secp' specifies the pointer to a variable to which the seconds is assigned. If it is `NULL', it is not used. .PP The function `cbdayofweek' is used in order to get the day of week of a date. .TP .B int cbdayofweek(int year, int mon, int day); `year' specifies the year of a date. `mon' specifies the month of the date. `day' specifies the day of the date. The return value is the day of week of the date. 0 means Sunday and 6 means Saturday. .PP The function `cbdatestrwww' is used in order to get the string for a date in W3CDTF. .TP .B char *cbdatestrwww(time_t t, int jl); `t' specifies a source time. If it is negative, the current time is specified. `jl' specifies the jet lag of a location in seconds. The return value is the string of the date in W3CDTF (YYYY\-MM\-DDThh:mm:ddTZD). Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. .PP The function `cbdatestrhttp' is used in order to get the string for a date in RFC 1123 format. .TP .B char *cbdatestrhttp(time_t t, int jl); `t' specifies a source time. If it is negative, the current time is specified. `jl' specifies the jet lag of a location in seconds. The return value is the string of the date in RFC 1123 format (Wdy, DD\-Mon\-YYYY hh:mm:dd TZD). Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. .PP The function `cbstrmktime' is used in order to get the time value of a date string in decimal, hexadecimal, W3CDTF, or RFC 822 (1123). .TP .B time_t cbstrmktime(const char *str); `str' specifies a date string in decimal, hexadecimal, W3CDTF, or RFC 822 (1123). The return value is the time value of the date or \-1 if the format is invalid. Decimal can be trailed by "s" for in seconds, "m" for in minutes, "h" for in hours, and "d" for in days. .PP The function `cbproctime' is used in order to get user and system processing times. .TP .B void cbproctime(double *usrp, double *sysp); `usrp' specifies the pointer to a variable to which the user processing time is assigned. If it is `NULL', it is not used. The unit of time is seconds. `sysp' specifies the pointer to a variable to which the system processing time is assigned. If it is `NULL', it is not used. The unit of time is seconds. .PP The function `cbstdiobin' is used in order to ensure that the standard I/O is binary mode. .TP .B void cbstdiobin(void); This function is useful for applications on dosish file systems. .PP Functions of Cabin except for `cbglobalgc' are thread\-safe as long as a handle is not accessed by threads at the same time, on the assumption that `errno', `malloc', and so on are thread\-safe. .SH SEE ALSO .PP .BR qdbm (3), .BR depot (3), .BR curia (3), .BR relic (3), .BR hovel (3), .BR villa (3), .BR odeum (3), .BR ndbm (3), .BR gdbm (3) qdbm-1.8.78/man/crmgr.10000644000175000017500000000670111426314237013522 0ustar mikiomikio.\" Hey, EMACS: -*- nroff -*- .\" First parameter, NAME, should be all caps .\" Second parameter, SECTION, should be 1-8, maybe w/ subsection .\" other parameters are allowed: see man(7), man(1) .TH CRMGR 1 "2005-05-23" "Man Page" "Quick Database Manager" .\" Please adjust this date whenever revising the manpage. .\" .\" Some roff macros, for reference: .\" .nh disable hyphenation .\" .hy enable hyphenation .\" .ad l left justify .\" .ad b justify to both left and right margins .\" .nf disable filling .\" .fi enable filling .\" .br insert line break .\" .sp insert n+1 empty lines .\" for manpage-specific macros, see man(7) .SH NAME crmgr \- administration utility for QDBM Curia .SH SYNOPSIS .B crmgr create .RI "[-s] [-bnum " num " ] [-dnum " num "] " name .br .B crmgr put .RI "[-kx|-ki] [-vx|-vi|-vf] [-keep|-cat] [-lob] [-na] " name " " key " " val .br .B crmgr out .RI "[-kx|-ki] [-lob] " name " " key .br .B crmgr get .RI "[-nl] [-kx|-ki] [-start " num "] [-max " num "] [-ox] [-lob] [-n] " name " " key .br .B crmgr list .RI "[-nl] [-k|-v] [-ox] " name .br .B crmgr optimize .RI "[-bnum " num "] [-na] " name .br .B crmgr inform .RI "[-nl] " name .br .B crmgr remove .I name .br .B crmgr repair .I name .br .B crmgr exportdb .I name dir .br .B crmgr importdb .I name dir .br .B crmgr snaffle .RI "[-kx|-ki] [-ox] [-n] " name " " key .br .B crmgr version .SH DESCRIPTION This manual page documents briefly the .B crmgr commands. .PP .\" TeX users may be more comfortable with the \fB\fP and .\" \fI\fP escape sequences to invode bold face and italics, .\" respectively. \fBcrmgr\fP is a utility for debugging Curia and its applications. It features editing and checking of a database. It can be used for the database applications with shell scripts. This command is used in the above format. \fIname\fP specifies a database name. \fIkey\fP specifies the key of a record. \fIval\fP specifies the value of a record. .SH OPTIONS A summary of options is included below. For a complete description, see the file:///usr/share/doc/qdbm-doc/spex.html#curiacli. .TP .B \-s make the file sparse. .TP .BI "\-bnum " num specify the number of the elements of the bucket array. .TP .BI "\-dnum " num specify the number of division of the database. .TP .B \-kx treat \fIkey\fP as a binary expression of hexadecimal notation. .TP .B \-ki treat \fIkey\fP as an integer expression of decimal notation. .TP .B \-vx treat \fIval\fP as a binary expression of hexadecimal notation. .TP .B \-vi treat \fIval\fP as an integer expression of decimal notation. .TP .B \-vf read the value from a file specified with \fIval\fP. .TP .B \-keep specify the storing mode for `CR_DKEEP'. .TP .B \-cat specify the storing mode for `CR_DCAT'. .TP .B \-na do not set alignment. .TP .B \-nl open the database without file locking. .TP .B \-start specify the beginning offset of a value to fetch. .TP .B \-max specify the max size of a value to fetch. .TP .B \-ox treat the output as a binary expression of hexadecimal notation. .TP .B \-lob handle large objects. .TP .B \-n do not output the tailing newline. .TP .B \-k output keys only. .TP .B \-v output values only. .SH SEE ALSO .BR qdbm (3), .BR crtsv (1), .BR curia (3), .BR cropen (3). .SH AUTHOR QDBM was written by Mikio Hirabayashi . .PP This manual page was written by Fumitoshi UKAI , for the Debian project (but may be used by others). qdbm-1.8.78/man/dpmgr.10000644000175000017500000000644111426314227013521 0ustar mikiomikio.\" Hey, EMACS: -*- nroff -*- .\" First parameter, NAME, should be all caps .\" Second parameter, SECTION, should be 1-8, maybe w/ subsection .\" other parameters are allowed: see man(7), man(1) .TH DPMGR 1 "2005-05-23" "Man Page" "Quick Database Manager" .\" Please adjust this date whenever revising the manpage. .\" .\" Some roff macros, for reference: .\" .nh disable hyphenation .\" .hy enable hyphenation .\" .ad l left justify .\" .ad b justify to both left and right margins .\" .nf disable filling .\" .fi enable filling .\" .br insert line break .\" .sp insert n+1 empty lines .\" for manpage-specific macros, see man(7) .SH NAME dpmgr \- administration utility for QDBM Depot .SH SYNOPSIS .B dpmgr create .RI "[-s] [-bnum " num "] " name .br .B dpmgr put .RI "[-kx|-ki] [-vx|-vi|-vf] [-keep|-cat] [-na] " name " " key " " val .br .B dpmgr out .RI "[-kx|-ki] " name " " key .br .B dpmgr get .RI "[-nl] [-kx|-ki] [-start " num "] [-max " num "] [-ox] [-n] " name " " key .br .B dpmgr list .RI "[-nl] [-k|-v] [-ox] " name .br .B dpmgr optimize .RI "[-bnum " num "] [-na] " name .br .B dpmgr inform .RI "[-nl] " name .br .B dpmgr remove .I name .br .B dpmgr repair .I name .br .B dpmgr exportdb .I name file .br .B dpmgr importdb .I name file .br .B dpmgr snaffle .RI "[-kx|-ki] [-ox] [-n] " name " " key .br .B dpmgr version .SH DESCRIPTION This manual page documents briefly the .B dpmgr commands. .PP .\" TeX users may be more comfortable with the \fB\fP and .\" \fI\fP escape sequences to invode bold face and italics, .\" respectively. \fBdpmgr\fP is a utility for debugging Depot and its applications. It features editing and checking of a database. It can be used for database applications with shell scripts. This command is used in the above format. \fIname\fP specifies a database name. \fIkey\fP specifies the key of a record. \fIval\fP specifies the value of a record. .SH OPTIONS A summary of options is included below. For a complete description, see the file:///usr/share/doc/qdbm-doc/spex.html#depotcli. .TP .B \-s make the file sparse. .TP .BI "\-bnum " num specify the number of the elements of the bucket array. .TP .B \-kx treat \fIkey\fP as a binary expression of hexadecimal notation. .TP .B \-ki treat \fIkey\fP as an integer expression of decimal notation. .TP .B \-vx treat \fIval\fP as a binary expression of hexadecimal notation. .TP .B \-vi treat \fIval\fP as an integer expression of decimal notation. .TP .B \-vf read the value from a file specified with \fIval\fP. .TP .B \-keep specify the storing mode for `DP_DKEEP'. .TP .B \-cat specify the storing mode for `DP_DCAT'. .TP .B \-na do not set alignment. .TP .B \-nl open the database without file locking. .TP .B \-start specify the beginning offset of a value to fetch. .TP .B \-max specify the max size of a value to fetch. .TP .B \-ox treat the output as a binary expression of hexadecimal notation. .TP .B \-n do not output the tailing newline. .TP .B \-k output keys only. .TP .B \-v output values only. .SH SEE ALSO .BR qdbm (3), .BR dptsv (1), .BR dpopen (3). .SH AUTHOR QDBM was written by Mikio Hirabayashi . .PP This manual page was written by Fumitoshi UKAI , for the Debian project (but may be used by others). qdbm-1.8.78/man/vlmgr.10000644000175000017500000000715311426314173013540 0ustar mikiomikio.\" Hey, EMACS: -*- nroff -*- .\" First parameter, NAME, should be all caps .\" Second parameter, SECTION, should be 1-8, maybe w/ subsection .\" other parameters are allowed: see man(7), man(1) .TH VLMGR 1 "2005-05-23" "Man Page" "Quick Database Manager" .\" Please adjust this date whenever revising the manpage. .\" .\" Some roff macros, for reference: .\" .nh disable hyphenation .\" .hy enable hyphenation .\" .ad l left justify .\" .ad b justify to both left and right margins .\" .nf disable filling .\" .fi enable filling .\" .br insert line break .\" .sp insert n+1 empty lines .\" for manpage-specific macros, see man(7) .SH NAME vlmgr \- administration utility for QDBM Villa .SH SYNOPSIS .B vlmgr create .RI "[-cz|-cy|-cx] " name .br .B vlmgr put .RI "[-kx|-ki] [-vx|-vi|-vf] [-keep|-cat|-dup] " name " " key " " val .br .B vlmgr out .RI "[-l] [-kx|-ki] " name " " key .br .B vlmgr get .RI "[-nl] [-l] [-kx|-ki] [-ox] [-n] " name " " key .br .B vlmgr list .RI "[-nl] [-k|-v] [-kx|-ki] [-ox] [-top " key "] [-bot " key "] [-gt] [-lt] [-max " num "] [-desc] " name .br .B vlmgr optimize .I name .br .B vlmgr inform .RI "[-nl] " name .br .B vlmgr remove .I name .br .B vlmgr repair .RI "[-ki] " name .br .B vlmgr exportdb .RI "[-ki] " name " " file .br .B vlmgr importdb .RI "[-ki] " name " " file .br .B vlmgr version .SH DESCRIPTION This manual page documents briefly the .B vlmgr commands. .PP .\" TeX users may be more comfortable with the \fB\fP and .\" \fI\fP escape sequences to invode bold face and italics, .\" respectively. \fBvlmgr\fP is a utility for debugging Villa and its applications. It features editing and checking of a database. It can be used for database applications with shell scripts. This command is used in the above format. \fIname\fP specifies a database name. \fIkey\fP specifies the key of a record. \fIval\fP specifies the value of a record. .SH OPTIONS A summary of options is included below. For a complete description, see the file:///usr/share/doc/qdbm-doc/spex.html#villacli. .TP .B \-cz compress leaves in the database with ZLIB. .TP .B \-cy compress leaves in the database with LZO. .TP .B \-cx compress leaves in the database with BZIP2. .TP .B \-l all records corresponding the key are dealt. .TP .B \-kx treat \fIkey\fP as a binary expression of hexadecimal notation. .TP .B \-ki treat \fIkey\fP as an integer expression of decimal notation. .TP .B \-vx treat \fIval\fP as a binary expression of hexadecimal notation. .TP .B \-vi treat \fIval\fP as an integer expression of decimal notation. .TP .B \-vf read the value from a file specified with \fIval\fP. .TP .B \-keep specify the storing mode for `VL_DKEEP'. .TP .B \-cat specify the storing mode for `VL_DCAT'. .TP .B \-dup specify the storing mode for `VL_DDUP'. .TP .B \-nl open the database without file locking. .TP .BI "\-top " key specify the top key of listing. .TP .BI "\-bot " key specify the bottom key of listing. .TP .B \-gt do not include the top key of listing. .TP .B \-lt do not include the bottom key of listing. .TP .BI "\-max " num specify the max number of listing. .TP .BI \-desc list in descending order. .TP .B \-ox treat the output as a binary expression of hexadecimal notation. .TP .B \-n do not output the tailing newline. .TP .B \-k output keys only. .TP .B \-v output values only. .SH SEE ALSO .BR qdbm (3) .BR vltsv (1), .BR villa (3), .BR vlopen (3). .SH AUTHOR QDBM was written by Mikio Hirabayashi . .PP This manual page was written by Fumitoshi UKAI , for the Debian project (but may be used by others). qdbm-1.8.78/qdbm.def0000644000175000017500000002605710572737543013176 0ustar mikiomikioEXPORTS VL_CMPDEC = VL_CMPDEC DATA VL_CMPINT = VL_CMPINT DATA VL_CMPLEX = VL_CMPLEX DATA VL_CMPNUM = VL_CMPNUM DATA VST_CMPDEC = VST_CMPDEC DATA VST_CMPINT = VST_CMPINT DATA VST_CMPLEX = VST_CMPLEX DATA VST_CMPNUM = VST_CMPNUM DATA cbfatalfunc = cbfatalfunc DATA dpdbgfd = dpdbgfd DATA dpisreentrant = dpisreentrant DATA dpsysname = dpsysname DATA dpversion = dpversion DATA gdbm_version = gdbm_version DATA odcachebnum = odcachebnum DATA odcachesiz = odcachesiz DATA odindexbnum = odindexbnum DATA odindexdnum = odindexdnum DATA odotcb = odotcb DATA cbbasedecode = cbbasedecode cbbaseencode = cbbaseencode cbbzdecode = cbbzdecode cbbzencode = cbbzencode cbcalendar = cbcalendar cbcsvcells = cbcsvcells cbcsvescape = cbcsvescape cbcsvrows = cbcsvrows cbcsvunescape = cbcsvunescape cbdatestrhttp = cbdatestrhttp cbdatestrwww = cbdatestrwww cbdatumcat = cbdatumcat cbdatumclose = cbdatumclose cbdatumdup = cbdatumdup cbdatumopen = cbdatumopen cbdatumopenbuf = cbdatumopenbuf cbdatumprintf = cbdatumprintf cbdatumptr = cbdatumptr cbdatumsetbuf = cbdatumsetbuf cbdatumsetsize = cbdatumsetsize cbdatumsize = cbdatumsize cbdatumtomalloc = cbdatumtomalloc cbdayofweek = cbdayofweek cbdeflate = cbdeflate cbdirlist = cbdirlist cbencname = cbencname cbfilestat = cbfilestat cbfree = cbfree cbgetcrc = cbgetcrc cbggcsweep = cbggcsweep cbglobalgc = cbglobalgc cbgzdecode = cbgzdecode cbgzencode = cbgzencode cbheapclose = cbheapclose cbheapdup = cbheapdup cbheapinsert = cbheapinsert cbheapnum = cbheapnum cbheapopen = cbheapopen cbheaptomalloc = cbheaptomalloc cbheapval = cbheapval cbhsort = cbhsort cbiconv = cbiconv cbinflate = cbinflate cbisort = cbisort cbjetlag = cbjetlag cblistbsearch = cblistbsearch cblistclose = cblistclose cblistdump = cblistdump cblistdup = cblistdup cblistinsert = cblistinsert cblistload = cblistload cblistlsearch = cblistlsearch cblistnum = cblistnum cblistopen = cblistopen cblistover = cblistover cblistpop = cblistpop cblistpush = cblistpush cblistpushbuf = cblistpushbuf cblistremove = cblistremove cblistshift = cblistshift cblistsort = cblistsort cblistunshift = cblistunshift cblistval = cblistval cblzodecode = cblzodecode cblzoencode = cblzoencode cbmalloc = cbmalloc cbmapclose = cbmapclose cbmapdump = cbmapdump cbmapdup = cbmapdup cbmapget = cbmapget cbmapiterinit = cbmapiterinit cbmapiternext = cbmapiternext cbmapiterval = cbmapiterval cbmapkeys = cbmapkeys cbmapload = cbmapload cbmaploadone = cbmaploadone cbmapmove = cbmapmove cbmapopen = cbmapopen cbmapopenex = cbmapopenex cbmapout = cbmapout cbmapput = cbmapput cbmapputcat = cbmapputcat cbmaprnum = cbmaprnum cbmapvals = cbmapvals cbmemdup = cbmemdup cbmimebreak = cbmimebreak cbmimedecode = cbmimedecode cbmimeencode = cbmimeencode cbmimeparts = cbmimeparts cbmyfatal = cbmyfatal cbproctime = cbproctime cbqsort = cbqsort cbquotedecode = cbquotedecode cbquoteencode = cbquoteencode cbreadfile = cbreadfile cbreadlines = cbreadlines cbrealloc = cbrealloc cbremove = cbremove cbreplace = cbreplace cbsplit = cbsplit cbsprintf = cbsprintf cbssort = cbssort cbstdiobin = cbstdiobin cbstrbwimatch = cbstrbwimatch cbstrbwmatch = cbstrbwmatch cbstrcountutf = cbstrcountutf cbstrcututf = cbstrcututf cbstrfwimatch = cbstrfwimatch cbstrfwmatch = cbstrfwmatch cbstricmp = cbstricmp cbstrmktime = cbstrmktime cbstrsqzspc = cbstrsqzspc cbstrstrbm = cbstrstrbm cbstrstrkmp = cbstrstrkmp cbstrtolower = cbstrtolower cbstrtoupper = cbstrtoupper cbstrtrim = cbstrtrim cburlbreak = cburlbreak cburldecode = cburldecode cburlencode = cburlencode cburlresolve = cburlresolve cbvmemavail = cbvmemavail cbwritefile = cbwritefile cbxmlattrs = cbxmlattrs cbxmlbreak = cbxmlbreak cbxmlescape = cbxmlescape cbxmlunescape = cbxmlunescape crbnum = crbnum crbusenum = crbusenum crclose = crclose crexportdb = crexportdb crfatalerror = crfatalerror crfsiz = crfsiz crfsizd = crfsizd crget = crget crgetflags = crgetflags crgetlob = crgetlob crgetlobfd = crgetlobfd crgetwb = crgetwb crimportdb = crimportdb crinode = crinode criterinit = criterinit criternext = criternext crmemflush = crmemflush crmemsync = crmemsync crmtime = crmtime crname = crname cropen = cropen croptimize = croptimize crout = crout croutlob = croutlob crput = crput crputlob = crputlob crremove = crremove crrepair = crrepair crrnum = crrnum crrnumlob = crrnumlob crsetalign = crsetalign crsetfbpsiz = crsetfbpsiz crsetflags = crsetflags crsnaffle = crsnaffle crsync = crsync crvsiz = crvsiz crvsizlob = crvsizlob crwritable = crwritable dbm_clearerr = dbm_clearerr dbm_close = dbm_close dbm_delete = dbm_delete dbm_dirfno = dbm_dirfno dbm_error = dbm_error dbm_fetch = dbm_fetch dbm_firstkey = dbm_firstkey dbm_nextkey = dbm_nextkey dbm_open = dbm_open dbm_pagfno = dbm_pagfno dbm_rdonly = dbm_rdonly dbm_store = dbm_store dpbnum = dpbnum dpbusenum = dpbusenum dpclose = dpclose dpecodeptr = dpecodeptr dpecodeset = dpecodeset dperrmsg = dperrmsg dpexportdb = dpexportdb dpfatalerror = dpfatalerror dpfdesc = dpfdesc dpfsiz = dpfsiz dpget = dpget dpgetflags = dpgetflags dpgetwb = dpgetwb dpimportdb = dpimportdb dpinnerhash = dpinnerhash dpinode = dpinode dpiterinit = dpiterinit dpiternext = dpiternext dpmemflush = dpmemflush dpmemsync = dpmemsync dpmtime = dpmtime dpname = dpname dpopen = dpopen dpoptimize = dpoptimize dpout = dpout dpouterhash = dpouterhash dpprimenum = dpprimenum dpput = dpput dpremove = dpremove dprepair = dprepair dprnum = dprnum dpsetalign = dpsetalign dpsetfbpsiz = dpsetfbpsiz dpsetflags = dpsetflags dpsnaffle = dpsnaffle dpsync = dpsync dpvsiz = dpvsiz dpwritable = dpwritable gdbm_close = gdbm_close gdbm_delete = gdbm_delete gdbm_errnoptr = gdbm_errnoptr gdbm_exists = gdbm_exists gdbm_fdesc = gdbm_fdesc gdbm_fetch = gdbm_fetch gdbm_firstkey = gdbm_firstkey gdbm_nextkey = gdbm_nextkey gdbm_open = gdbm_open gdbm_open2 = gdbm_open2 gdbm_reorganize = gdbm_reorganize gdbm_setopt = gdbm_setopt gdbm_store = gdbm_store gdbm_strerror = gdbm_strerror gdbm_sync = gdbm_sync odanalyzetext = odanalyzetext odbnum = odbnum odbreaktext = odbreaktext odbusenum = odbusenum odcheck = odcheck odclose = odclose oddnum = oddnum oddocaddattr = oddocaddattr oddocaddword = oddocaddword oddocawords = oddocawords oddocclose = oddocclose oddocgetattr = oddocgetattr oddocid = oddocid oddocnwords = oddocnwords oddocopen = oddocopen oddocscores = oddocscores oddocuri = oddocuri odfatalerror = odfatalerror odfsiz = odfsiz odget = odget odgetbyid = odgetbyid odgetidbyuri = odgetidbyuri odidbdocs = odidbdocs odidbindex = odidbindex odidbrdocs = odidbrdocs odinode = odinode oditerinit = oditerinit oditernext = oditernext odlogarithm = odlogarithm odmerge = odmerge odmtime = odmtime odname = odname odnormalizeword = odnormalizeword odopen = odopen odoptimize = odoptimize odout = odout odoutbyid = odoutbyid odpairsand = odpairsand odpairsnotand = odpairsnotand odpairsor = odpairsor odpairssort = odpairssort odput = odput odquery = odquery odremove = odremove odsearch = odsearch odsearchdnum = odsearchdnum odsetcharclass = odsetcharclass odsetotcb = odsetotcb odsettuning = odsettuning odsquareroot = odsquareroot odsync = odsync odvecabsolute = odvecabsolute odvecinnerproduct = odvecinnerproduct odvectorcosine = odvectorcosine odwnum = odwnum odwritable = odwritable vlclose = vlclose vlcrdnumptr = vlcrdnumptr vlcurfirst = vlcurfirst vlcurjump = vlcurjump vlcurkey = vlcurkey vlcurkeycache = vlcurkeycache vlcurlast = vlcurlast vlcurnext = vlcurnext vlcurout = vlcurout vlcurprev = vlcurprev vlcurput = vlcurput vlcurval = vlcurval vlcurvalcache = vlcurvalcache vlexportdb = vlexportdb vlfatalerror = vlfatalerror vlfsiz = vlfsiz vlget = vlget vlgetcache = vlgetcache vlgetcat = vlgetcat vlgetflags = vlgetflags vlgetlist = vlgetlist vlimportdb = vlimportdb vlinode = vlinode vllnum = vllnum vlmemflush = vlmemflush vlmemsync = vlmemsync vlmtime = vlmtime vlmulcurclose = vlmulcurclose vlmulcurfirst = vlmulcurfirst vlmulcurjump = vlmulcurjump vlmulcurkey = vlmulcurkey vlmulcurkeycache = vlmulcurkeycache vlmulcurlast = vlmulcurlast vlmulcurnext = vlmulcurnext vlmulcuropen = vlmulcuropen vlmulcurprev = vlmulcurprev vlmulcurval = vlmulcurval vlmulcurvalcache = vlmulcurvalcache vlname = vlname vlnnum = vlnnum vlopen = vlopen vloptimize = vloptimize vlout = vlout vloutlist = vloutlist vlput = vlput vlputlist = vlputlist vlremove = vlremove vlrepair = vlrepair vlrnum = vlrnum vlsetfbpsiz = vlsetfbpsiz vlsetflags = vlsetflags vlsettuning = vlsettuning vlsync = vlsync vltranabort = vltranabort vltranbegin = vltranbegin vltrancommit = vltrancommit vlvnum = vlvnum vlvsiz = vlvsiz vlwritable = vlwritable vstclose = vstclose vstcrdnumptr = vstcrdnumptr vstcurfirst = vstcurfirst vstcurjump = vstcurjump vstcurkey = vstcurkey vstcurkeycache = vstcurkeycache vstcurlast = vstcurlast vstcurnext = vstcurnext vstcurout = vstcurout vstcurprev = vstcurprev vstcurput = vstcurput vstcurval = vstcurval vstcurvalcache = vstcurvalcache vstexportdb = vstexportdb vstfatalerror = vstfatalerror vstfsiz = vstfsiz vstget = vstget vstgetcache = vstgetcache vstgetcat = vstgetcat vstgetflags = vstgetflags vstgetlist = vstgetlist vstimportdb = vstimportdb vstinode = vstinode vstlnum = vstlnum vstmemflush = vstmemflush vstmemsync = vstmemsync vstmtime = vstmtime vstmulcurclose = vstmulcurclose vstmulcurfirst = vstmulcurfirst vstmulcurjump = vstmulcurjump vstmulcurkey = vstmulcurkey vstmulcurkeycache = vstmulcurkeycache vstmulcurlast = vstmulcurlast vstmulcurnext = vstmulcurnext vstmulcuropen = vstmulcuropen vstmulcurprev = vstmulcurprev vstmulcurval = vstmulcurval vstmulcurvalcache = vstmulcurvalcache vstname = vstname vstnnum = vstnnum vstopen = vstopen vstoptimize = vstoptimize vstout = vstout vstoutlist = vstoutlist vstput = vstput vstputlist = vstputlist vstremove = vstremove vstrepair = vstrepair vstrnum = vstrnum vstsetfbpsiz = vstsetfbpsiz vstsetflags = vstsetflags vstsettuning = vstsettuning vstsync = vstsync vsttranabort = vsttranabort vsttranbegin = vsttranbegin vsttrancommit = vsttrancommit vstvnum = vstvnum vstvsiz = vstvsiz vstwritable = vstwritable qdbm-1.8.78/odeum.c0000644000175000017500000017357010610627747013050 0ustar mikiomikio/************************************************************************************************* * Implementation of Odeum * Copyright (C) 2000-2007 Mikio Hirabayashi * This file is part of QDBM, Quick Database Manager. * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU * Lesser General Public License as published by the Free Software Foundation; either version * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * You should have received a copy of the GNU Lesser General Public License along with QDBM; if * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. *************************************************************************************************/ #define QDBM_INTERNAL 1 #include "odeum.h" #include "myconf.h" #define OD_NAMEMAX 256 /* max size of a database name */ #define OD_DIRMODE 00755 /* permission of a creating directory */ #define OD_PATHBUFSIZ 1024 /* size of a path buffer */ #define OD_NUMBUFSIZ 32 /* size of a buffer for a number */ #define OD_MAPPBNUM 127 /* bucket size of a petit map handle */ #define OD_DOCSNAME "docs" /* name of the database for documents */ #define OD_INDEXNAME "index" /* name of the database for inverted index */ #define OD_RDOCSNAME "rdocs" /* name of the database for reverse dictionary */ #define OD_DOCSBNUM 2039 /* initial bucket number of document database */ #define OD_DOCSDNUM 17 /* division number of document database */ #define OD_DOCSALIGN -4 /* alignment of document database */ #define OD_DOCSFBP 32 /* size of free block pool of document database */ #define OD_INDEXBNUM 32749 /* initial bucket number of inverted index */ #define OD_INDEXDNUM 7 /* division number of inverted index */ #define OD_INDEXALIGN -2 /* alignment of inverted index */ #define OD_INDEXFBP 32 /* size of free block pool of inverted index */ #define OD_RDOCSLRM 81 /* records in a leaf node of reverse dictionary */ #define OD_RDOCSNIM 192 /* records in a non-leaf node of reverse dictionary */ #define OD_RDOCSLCN 128 /* number of leaf cache of reverse dictionary */ #define OD_RDOCSNCN 32 /* number of non-leaf cache of reverse dictionary */ #define OD_CACHEBNUM 262139 /* number of buckets for dirty buffers */ #define OD_CACHESIZ 8388608 /* max bytes to use memory for dirty buffers */ #define OD_CFLIVERAT 0.8 /* ratio of usable cache region */ #define OD_CFBEGSIZ 2048 /* beginning size of flushing frequent words */ #define OD_CFENDSIZ 64 /* lower limit of flushing frequent words */ #define OD_CFRFRAT 0.2 /* ratio of flushing rare words a time */ #define OD_OTCBBUFSIZ 1024 /* size of a buffer for call back functions */ #define OD_OTPERWORDS 10000 /* frequency of call back in merging index */ #define OD_OTPERDOCS 1000 /* frequency of call back in merging docs */ #define OD_MDBRATIO 2.5 /* ratio of bucket number and document number */ #define OD_MIBRATIO 1.5 /* ratio of bucket number and word number */ #define OD_MIARATIO 0.75 /* ratio of alignment to the first words */ #define OD_MIWUNIT 32 /* writing unit of merging inverted index */ #define OD_DMAXEXPR "dmax" /* key of max number of the document ID */ #define OD_DNUMEXPR "dnum" /* key of number of the documents */ #define OD_URIEXPR "1" /* map key of URI */ #define OD_ATTRSEXPR "2" /* map key of attributes */ #define OD_NWORDSEXPR "3" /* map key of normal words */ #define OD_AWORDSEXPR "4" /* map key of as-is words */ #define OD_WTOPRATE 0.1 /* ratio of top words */ #define OD_WTOPBONUS 5000 /* bonus points of top words */ #define OD_KEYCRATIO 1.75 /* ratio of number to max of keyword candidates */ #define OD_WOCCRPOINT 10000 /* points per occurence */ #define OD_SPACECHARS "\t\n\v\f\r " /* space characters */ #define OD_DELIMCHARS "!\"#$%&'()*/<=>?[\\]^`{|}~" /* delimiter characters */ #define OD_GLUECHARS "+,-.:;@" /* glueing characters */ #define OD_MAXWORDLEN 48 /* max length of a word */ typedef struct { /* type of structure for word counting */ const char *word; /* pointer to the word */ int num; /* frequency of the word */ } ODWORD; enum { /* enumeration for events binded to each character */ OD_EVWORD, /* word */ OD_EVSPACE, /* space */ OD_EVDELIM, /* delimiter */ OD_EVGLUE /* glue */ }; /* private global variables */ int odindexbnum = OD_INDEXBNUM; int odindexdnum = OD_INDEXDNUM; int odcachebnum = OD_CACHEBNUM; int odcachesiz = OD_CACHESIZ; void (*odotcb)(const char *, ODEUM *, const char *) = NULL; /* private function prototypes */ static ODEUM *odopendb(const char *name, int omode, int docsbnum, int indexbnum, const char *fname); static int odcacheflush(ODEUM *odeum, const char *fname); static int odcacheflushfreq(ODEUM *odeum, const char *fname, int min); static int odcacheflushrare(ODEUM *odeum, const char *fname, double ratio); static int odsortindex(ODEUM *odeum, const char *fname); static int odsortcompare(const void *a, const void *b); static int odpurgeindex(ODEUM *odeum, const char *fname); static CBMAP *odpairsmap(const ODPAIR *pairs, int num); static int odwordcompare(const void *a, const void *b); static int odmatchoperator(ODEUM *odeum, CBLIST *tokens); static ODPAIR *odparsesubexpr(ODEUM *odeum, CBLIST *tokens, CBLIST *nwords, int *np, CBLIST *errors); static ODPAIR *odparseexpr(ODEUM *odeum, CBLIST *tokens, CBLIST *nwords, int *np, CBLIST *errors); static void odfixtokens(ODEUM *odeum, CBLIST *tokens); static void odcleannormalized(ODEUM *odeum, CBLIST *nwords); /************************************************************************************************* * public objects *************************************************************************************************/ /* Get a database handle. */ ODEUM *odopen(const char *name, int omode){ assert(name); return odopendb(name, omode, OD_DOCSBNUM, odindexbnum, "odopen"); } /* Close a database handle. */ int odclose(ODEUM *odeum){ char numbuf[OD_NUMBUFSIZ]; int err; assert(odeum); err = FALSE; if(odotcb) odotcb("odclose", odeum, "closing the connection"); if(odeum->wmode){ if(odotcb) odotcb("odclose", odeum, "writing meta information"); sprintf(numbuf, "%d", odeum->dmax); if(!vlput(odeum->rdocsdb, OD_DMAXEXPR, sizeof(OD_DMAXEXPR), numbuf, -1, VL_DOVER)) err = TRUE; sprintf(numbuf, "%d", odeum->dnum); if(!vlput(odeum->rdocsdb, OD_DNUMEXPR, sizeof(OD_DNUMEXPR), numbuf, -1, VL_DOVER)) err = TRUE; if(!odcacheflushfreq(odeum, "odclose", OD_CFENDSIZ)) err = TRUE; if(!odcacheflushrare(odeum, "odclose", OD_CFRFRAT)) err = TRUE; if(!odcacheflush(odeum, "odclose")) err = TRUE; if(!odsortindex(odeum, "odclose")) err = TRUE; cbmapclose(odeum->cachemap); cbmapclose(odeum->sortmap); } if(!vlclose(odeum->rdocsdb)) err = TRUE; if(!crclose(odeum->indexdb)) err = TRUE; if(!crclose(odeum->docsdb)) err = TRUE; free(odeum->name); free(odeum); return err ? FALSE : TRUE; } /* Store a document. */ int odput(ODEUM *odeum, ODDOC *doc, int wmax, int over){ char *tmp, *zbuf; const char *word, *ctmp; int i, docid, tsiz, wsiz, wnum, tmax, num, zsiz; double ival; ODPAIR pair; CBMAP *map; CBLIST *tlist; assert(odeum); if(odeum->fatal){ dpecodeset(DP_EFATAL, __FILE__, __LINE__); return FALSE; } if(!odeum->wmode){ dpecodeset(DP_EMODE, __FILE__, __LINE__); return FALSE; } if((tmp = vlget(odeum->rdocsdb, doc->uri, -1, &tsiz)) != NULL){ if(!over){ free(tmp); dpecodeset(DP_EKEEP, __FILE__, __LINE__); return FALSE; } if(tsiz != sizeof(int) || !odoutbyid(odeum, *(int *)tmp)){ free(tmp); dpecodeset(DP_EBROKEN, __FILE__, __LINE__); odeum->fatal = TRUE; return FALSE; } free(tmp); } odeum->dmax++; odeum->dnum++; docid = odeum->dmax; map = cbmapopen(); cbmapput(map, OD_URIEXPR, sizeof(OD_URIEXPR), doc->uri, -1, TRUE); tmp = cbmapdump(doc->attrs, &tsiz); cbmapput(map, OD_ATTRSEXPR, sizeof(OD_ATTRSEXPR), tmp, tsiz, TRUE); free(tmp); if(wmax < 0 || wmax > cblistnum(doc->nwords)) wmax = cblistnum(doc->nwords); tlist = cblistopen(); for(i = 0; i < wmax; i++){ ctmp = cblistval(doc->nwords, i, &wsiz); cblistpush(tlist, ctmp, wsiz); } tmp = cblistdump(tlist, &tsiz); cbmapput(map, OD_NWORDSEXPR, sizeof(OD_NWORDSEXPR), tmp, tsiz, TRUE); free(tmp); cblistclose(tlist); tlist = cblistopen(); for(i = 0; i < wmax; i++){ ctmp = cblistval(doc->awords, i, &wsiz); if(strcmp(ctmp, cblistval(doc->nwords, i, NULL))){ cblistpush(tlist, ctmp, wsiz); } else { cblistpush(tlist, "\0", 1); } } tmp = cblistdump(tlist, &tsiz); cbmapput(map, OD_AWORDSEXPR, sizeof(OD_AWORDSEXPR), tmp, tsiz, TRUE); free(tmp); cblistclose(tlist); tmp = cbmapdump(map, &tsiz); cbmapclose(map); if(_qdbm_deflate){ if(!(zbuf = _qdbm_deflate(tmp, tsiz, &zsiz, _QDBM_ZMRAW))){ free(tmp); dpecodeset(DP_EMISC, __FILE__, __LINE__); odeum->fatal = TRUE; return FALSE; } free(tmp); tmp = zbuf; tsiz = zsiz; } if(!crput(odeum->docsdb, (char *)&docid, sizeof(int), tmp, tsiz, CR_DKEEP)){ free(tmp); if(dpecode == DP_EKEEP) dpecodeset(DP_EBROKEN, __FILE__, __LINE__); odeum->fatal = TRUE; return FALSE; } free(tmp); if(!vlput(odeum->rdocsdb, doc->uri, -1, (char *)&docid, sizeof(int), VL_DOVER)){ odeum->fatal = TRUE; return FALSE; } map = cbmapopen(); wnum = cblistnum(doc->nwords); tmax = (int)(wnum * OD_WTOPRATE); for(i = 0; i < wnum; i++){ word = cblistval(doc->nwords, i, &wsiz); if(wsiz < 1) continue; if((ctmp = cbmapget(map, word, wsiz, NULL)) != NULL){ num = *(int *)ctmp + OD_WOCCRPOINT; } else { num = i <= tmax ? OD_WTOPBONUS + OD_WOCCRPOINT : OD_WOCCRPOINT; } cbmapput(map, word, wsiz, (char *)&num, sizeof(int), TRUE); } ival = odlogarithm(wnum); ival = (ival * ival * ival) / 8.0; if(ival < 8.0) ival = 8.0; cbmapiterinit(map); while((word = cbmapiternext(map, &wsiz)) != NULL){ pair.id = docid; pair.score = (int)(*(int *)cbmapget(map, word, wsiz, NULL) / ival); cbmapputcat(odeum->cachemap, word, wsiz, (char *)&pair, sizeof(pair)); cbmapmove(odeum->cachemap, word, wsiz, FALSE); odeum->cacheasiz += sizeof(pair); cbmapput(odeum->sortmap, word, wsiz, "", 0, FALSE); } cbmapclose(map); if(odeum->cacheasiz > odcachesiz){ for(i = OD_CFBEGSIZ; odeum->cacheasiz > odcachesiz * OD_CFLIVERAT && i >= OD_CFENDSIZ; i /= 2){ if(!odcacheflushfreq(odeum, "odput", i)) return FALSE; } while(odeum->cacheasiz > odcachesiz * OD_CFLIVERAT){ if(!odcacheflushrare(odeum, "odput", OD_CFRFRAT)) return FALSE; } } doc->id = docid; odeum->ldid = docid; return TRUE; } /* Delete a document by a URL. */ int odout(ODEUM *odeum, const char *uri){ char *tmp; int tsiz, docid; assert(odeum && uri); if(odeum->fatal){ dpecodeset(DP_EFATAL, __FILE__, __LINE__); return FALSE; } if(!odeum->wmode){ dpecodeset(DP_EMODE, __FILE__, __LINE__); return FALSE; } if(!(tmp = vlget(odeum->rdocsdb, uri, -1, &tsiz))){ if(dpecode != DP_ENOITEM) odeum->fatal = TRUE; return FALSE; } if(tsiz != sizeof(int)){ free(tmp); dpecodeset(DP_EBROKEN, __FILE__, __LINE__); odeum->fatal = TRUE; return FALSE; } docid = *(int *)tmp; free(tmp); return odoutbyid(odeum, docid); } /* Delete a document specified by an ID number. */ int odoutbyid(ODEUM *odeum, int id){ char *tmp, *zbuf; const char *uritmp; int tsiz, uritsiz, zsiz; CBMAP *map; assert(odeum && id > 0); if(odeum->fatal){ dpecodeset(DP_EFATAL, __FILE__, __LINE__); return FALSE; } if(!odeum->wmode){ dpecodeset(DP_EMODE, __FILE__, __LINE__); return FALSE; } if(!(tmp = crget(odeum->docsdb, (char *)&id, sizeof(int), 0, -1, &tsiz))){ if(dpecode != DP_ENOITEM) odeum->fatal = TRUE; return FALSE; } if(_qdbm_inflate){ if(!(zbuf = _qdbm_inflate(tmp, tsiz, &zsiz, _QDBM_ZMRAW))){ free(tmp); dpecodeset(DP_EBROKEN, __FILE__, __LINE__); odeum->fatal = TRUE; return FALSE; } free(tmp); tmp = zbuf; tsiz = zsiz; } map = cbmapload(tmp, tsiz); free(tmp); uritmp = cbmapget(map, OD_URIEXPR, sizeof(OD_URIEXPR), &uritsiz); if(!uritmp || !vlout(odeum->rdocsdb, uritmp, uritsiz)){ cbmapclose(map); dpecodeset(DP_EBROKEN, __FILE__, __LINE__); odeum->fatal = TRUE; return FALSE; } cbmapclose(map); if(!crout(odeum->docsdb, (char *)&id, sizeof(int))){ odeum->fatal = TRUE; return FALSE; } odeum->dnum--; return TRUE; } /* Retrieve a document by a URI. */ ODDOC *odget(ODEUM *odeum, const char *uri){ char *tmp; int tsiz, docid; assert(odeum && uri); if(odeum->fatal){ dpecodeset(DP_EFATAL, __FILE__, __LINE__); return NULL; } if(!(tmp = vlget(odeum->rdocsdb, uri, -1, &tsiz))){ if(dpecode != DP_ENOITEM) odeum->fatal = TRUE; return NULL; } if(tsiz != sizeof(int)){ free(tmp); dpecodeset(DP_EBROKEN, __FILE__, __LINE__); odeum->fatal = TRUE; return NULL; } docid = *(int *)tmp; free(tmp); return odgetbyid(odeum, docid); } /* Retrieve a document by an ID number. */ ODDOC *odgetbyid(ODEUM *odeum, int id){ char *tmp, *zbuf; const char *uritmp, *attrstmp, *nwordstmp, *awordstmp, *asis, *normal; int i, tsiz, uritsiz, attrstsiz, nwordstsiz, awordstsiz, zsiz, asiz, nsiz; ODDOC *doc; CBMAP *map; assert(odeum); if(odeum->fatal){ dpecodeset(DP_EFATAL, __FILE__, __LINE__); return NULL; } if(id < 1){ dpecodeset(DP_ENOITEM, __FILE__, __LINE__); return NULL; } if(!(tmp = crget(odeum->docsdb, (char *)&id, sizeof(int), 0, -1, &tsiz))){ if(dpecode != DP_ENOITEM) odeum->fatal = TRUE; return NULL; } if(_qdbm_inflate){ if(!(zbuf = _qdbm_inflate(tmp, tsiz, &zsiz, _QDBM_ZMRAW))){ free(tmp); dpecodeset(DP_EBROKEN, __FILE__, __LINE__); odeum->fatal = TRUE; return NULL; } free(tmp); tmp = zbuf; tsiz = zsiz; } map = cbmapload(tmp, tsiz); free(tmp); uritmp = cbmapget(map, OD_URIEXPR, sizeof(OD_URIEXPR), &uritsiz); attrstmp = cbmapget(map, OD_ATTRSEXPR, sizeof(OD_ATTRSEXPR), &attrstsiz); nwordstmp = cbmapget(map, OD_NWORDSEXPR, sizeof(OD_NWORDSEXPR), &nwordstsiz); awordstmp = cbmapget(map, OD_AWORDSEXPR, sizeof(OD_AWORDSEXPR), &awordstsiz); if(!uritmp || !attrstmp || !nwordstmp || !awordstmp){ cbmapclose(map); dpecodeset(DP_EBROKEN, __FILE__, __LINE__); odeum->fatal = TRUE; return NULL; } doc = cbmalloc(sizeof(ODDOC)); doc->id = id; doc->uri = cbmemdup(uritmp, uritsiz); doc->attrs = cbmapload(attrstmp, attrstsiz); doc->nwords = cblistload(nwordstmp, nwordstsiz); doc->awords = cblistload(awordstmp, awordstsiz); cbmapclose(map); for(i = 0; i < cblistnum(doc->awords); i++){ asis = cblistval(doc->awords, i, &asiz); if(asiz == 1 && asis[0] == '\0'){ normal = cblistval(doc->nwords, i, &nsiz); cblistover(doc->awords, i, normal, nsiz); } } return doc; } /* Retrieve the ID of the document specified by a URI. */ int odgetidbyuri(ODEUM *odeum, const char *uri){ char *tmp; int tsiz, docid; assert(odeum && uri); if(odeum->fatal){ dpecodeset(DP_EFATAL, __FILE__, __LINE__); return -1; } if(!(tmp = vlget(odeum->rdocsdb, uri, -1, &tsiz))){ if(dpecode != DP_ENOITEM) odeum->fatal = TRUE; return -1; } if(tsiz != sizeof(int)){ free(tmp); dpecodeset(DP_EBROKEN, __FILE__, __LINE__); odeum->fatal = TRUE; return -1; } docid = *(int *)tmp; free(tmp); return docid; } /* Check whether the document specified by an ID number exists. */ int odcheck(ODEUM *odeum, int id){ assert(odeum); if(odeum->fatal){ dpecodeset(DP_EFATAL, __FILE__, __LINE__); return FALSE; } if(id < 1){ dpecodeset(DP_ENOITEM, __FILE__, __LINE__); return FALSE; } return crvsiz(odeum->docsdb, (char *)&id, sizeof(int)) != -1; } /* Search the inverted index for documents including a word. */ ODPAIR *odsearch(ODEUM *odeum, const char *word, int max, int *np){ char *tmp; int tsiz; assert(odeum && word && np); if(odeum->fatal){ dpecodeset(DP_EFATAL, __FILE__, __LINE__); return NULL; } if(odeum->wmode && cbmaprnum(odeum->sortmap) > 0 && (!odcacheflush(odeum, "odsearch") || !odsortindex(odeum, "odsearch"))){ odeum->fatal = TRUE; return NULL; } max = max < 0 ? -1 : max * sizeof(ODPAIR); if(!(tmp = crget(odeum->indexdb, word, -1, 0, max, &tsiz))){ if(dpecode != DP_ENOITEM){ odeum->fatal = TRUE; return NULL; } *np = 0; return cbmalloc(1); } *np = tsiz / sizeof(ODPAIR); return (ODPAIR *)tmp; } /* Get the number of documents including a word. */ int odsearchdnum(ODEUM *odeum, const char *word){ int rv; assert(odeum && word); if(odeum->fatal){ dpecodeset(DP_EFATAL, __FILE__, __LINE__); return -1; } rv = crvsiz(odeum->indexdb, word, -1); return rv < 0 ? -1 : rv / sizeof(ODPAIR); } /* Initialize the iterator of a database handle. */ int oditerinit(ODEUM *odeum){ assert(odeum); if(odeum->fatal){ dpecodeset(DP_EFATAL, __FILE__, __LINE__); return FALSE; } return criterinit(odeum->docsdb); } /* Get the next key of the iterator. */ ODDOC *oditernext(ODEUM *odeum){ char *tmp; int tsiz, docsid; ODDOC *doc; assert(odeum); if(odeum->fatal){ dpecodeset(DP_EFATAL, __FILE__, __LINE__); return NULL; } doc = NULL; while(TRUE){ if(!(tmp = criternext(odeum->docsdb, &tsiz))){ if(dpecode != DP_ENOITEM) odeum->fatal = TRUE; return NULL; } if(tsiz != sizeof(int)){ free(tmp); dpecodeset(DP_EBROKEN, __FILE__, __LINE__); odeum->fatal = TRUE; return NULL; } docsid = *(int *)tmp; free(tmp); if((doc = odgetbyid(odeum, docsid)) != NULL) break; if(dpecode != DP_ENOITEM){ odeum->fatal = TRUE; return NULL; } } return doc; } /* Synchronize updating contents with the files and the devices. */ int odsync(ODEUM *odeum){ char numbuf[OD_NUMBUFSIZ]; assert(odeum); if(odeum->fatal){ dpecodeset(DP_EFATAL, __FILE__, __LINE__); return FALSE; } if(!odeum->wmode){ dpecodeset(DP_EMODE, __FILE__, __LINE__); return FALSE; } if(odotcb) odotcb("odsync", odeum, "writing meta information"); sprintf(numbuf, "%d", odeum->dmax); if(!vlput(odeum->rdocsdb, OD_DMAXEXPR, sizeof(OD_DMAXEXPR), numbuf, -1, VL_DOVER)){ odeum->fatal = TRUE; return FALSE; } sprintf(numbuf, "%d", odeum->dnum); if(!vlput(odeum->rdocsdb, OD_DNUMEXPR, sizeof(OD_DNUMEXPR), numbuf, -1, VL_DOVER)){ odeum->fatal = TRUE; return FALSE; } if(!odcacheflush(odeum, "odsync")){ odeum->fatal = TRUE; return FALSE; } if(!odsortindex(odeum, "odsync")){ odeum->fatal = TRUE; return FALSE; } if(odotcb) odotcb("odsync", odeum, "synchronizing the document database"); if(!crsync(odeum->docsdb)){ odeum->fatal = TRUE; return FALSE; } if(odotcb) odotcb("odsync", odeum, "synchronizing the inverted index"); if(!crsync(odeum->indexdb)){ odeum->fatal = TRUE; return FALSE; } if(odotcb) odotcb("odsync", odeum, "synchronizing the reverse dictionary"); if(!vlsync(odeum->rdocsdb)){ odeum->fatal = TRUE; return FALSE; } return TRUE; } /* Optimize a database. */ int odoptimize(ODEUM *odeum){ assert(odeum); if(odeum->fatal){ dpecodeset(DP_EFATAL, __FILE__, __LINE__); return FALSE; } if(!odeum->wmode){ dpecodeset(DP_EMODE, __FILE__, __LINE__); return FALSE; } if(!odcacheflush(odeum, "odoptimize")){ odeum->fatal = TRUE; return FALSE; } if(odeum->ldid < 1 || odeum->ldid != odeum->dnum){ if(!odpurgeindex(odeum, "odoptimize")){ odeum->fatal = TRUE; return FALSE; } } if(odeum->ldid > 0){ if(!odsortindex(odeum, "odoptimize")){ odeum->fatal = TRUE; return FALSE; } } if(odotcb) odotcb("odoptimize", odeum, "optimizing the document database"); if(!croptimize(odeum->docsdb, -1)){ odeum->fatal = TRUE; return FALSE; } if(odotcb) odotcb("odoptimize", odeum, "optimizing the inverted index"); if(!croptimize(odeum->indexdb, -1)){ odeum->fatal = TRUE; return FALSE; } if(odotcb) odotcb("odoptimize", odeum, "optimizing the reverse dictionary"); if(!vloptimize(odeum->rdocsdb)){ odeum->fatal = TRUE; return FALSE; } return TRUE; } /* Get the name of a database. */ char *odname(ODEUM *odeum){ assert(odeum); if(odeum->fatal){ dpecodeset(DP_EFATAL, __FILE__, __LINE__); return NULL; } return cbmemdup(odeum->name, -1); } /* Get the total size of database files. */ double odfsiz(ODEUM *odeum){ double fsiz, rv; assert(odeum); if(odeum->fatal){ dpecodeset(DP_EFATAL, __FILE__, __LINE__); return -1; } fsiz = 0; if((rv = crfsizd(odeum->docsdb)) < 0) return -1.0; fsiz += rv; if((rv = crfsizd(odeum->indexdb)) < 0) return -1.0; fsiz += rv; if((rv = vlfsiz(odeum->rdocsdb)) == -1) return -1.0; fsiz += rv; return fsiz; } /* Get the total number of the elements of the bucket arrays for the inverted index. */ int odbnum(ODEUM *odeum){ assert(odeum); if(odeum->fatal){ dpecodeset(DP_EFATAL, __FILE__, __LINE__); return -1; } return crbnum(odeum->indexdb); } /* Get the total number of the used elements of the bucket arrays in the inverted index. */ int odbusenum(ODEUM *odeum){ assert(odeum); if(odeum->fatal){ dpecodeset(DP_EFATAL, __FILE__, __LINE__); return -1; } return crbusenum(odeum->indexdb); } /* Get the number of the documents stored in a database. */ int oddnum(ODEUM *odeum){ assert(odeum); if(odeum->fatal){ dpecodeset(DP_EFATAL, __FILE__, __LINE__); return -1; } return odeum->dnum; } /* Get the number of the words stored in a database. */ int odwnum(ODEUM *odeum){ assert(odeum); if(odeum->fatal){ dpecodeset(DP_EFATAL, __FILE__, __LINE__); return -1; } return crrnum(odeum->indexdb); } /* Check whether a database handle is a writer or not. */ int odwritable(ODEUM *odeum){ assert(odeum); return odeum->wmode; } /* Check whether a database has a fatal error or not. */ int odfatalerror(ODEUM *odeum){ assert(odeum); return odeum->fatal; } /* Get the inode number of a database directory. */ int odinode(ODEUM *odeum){ assert(odeum); return odeum->inode; } /* Get the last modified time of a database. */ time_t odmtime(ODEUM *odeum){ assert(odeum); return crmtime(odeum->indexdb); } /* Merge plural database directories. */ int odmerge(const char *name, const CBLIST *elemnames){ ODEUM *odeum, **elems; CURIA *curia, *ecuria; VILLA *villa, *evilla; ODPAIR *pairs; char *word, *kbuf, *vbuf, *dbuf, otmsg[OD_OTCBBUFSIZ]; char *wpunit[OD_MIWUNIT], *vpunit[OD_MIWUNIT]; int i, j, k, num, dnum, wnum, dbnum, ibnum, tnum, wsunit[OD_MIWUNIT], vsunit[OD_MIWUNIT]; int err, *bases, sum, max, wsiz, ksiz, vsiz, uend, unum, pnum, align, id, nid, dsiz; assert(name && elemnames); num = cblistnum(elemnames); elems = cbmalloc(num * sizeof(ODEUM *) + 1); dnum = 0; wnum = 0; for(i = 0; i < num; i++){ if(!(elems[i] = odopen(cblistval(elemnames, i, NULL), OD_OREADER))){ for(i -= 1; i >= 0; i--){ odclose(elems[i]); } free(elems); return FALSE; } dnum += oddnum(elems[i]); wnum += odwnum(elems[i]); } dbnum = (int)(dnum * OD_MDBRATIO / OD_DOCSDNUM); ibnum = (int)(wnum * OD_MIBRATIO / odindexdnum); if(!(odeum = odopendb(name, OD_OWRITER | OD_OCREAT | OD_OTRUNC, dbnum, ibnum, "odmerge"))){ for(i = 0; i < num; i++){ odclose(elems[i]); } free(elems); return FALSE; } err = FALSE; if(odotcb) odotcb("odmerge", odeum, "calculating the base ID numbers"); bases = cbmalloc(num * sizeof(int) + 1); sum = 0; for(i = 0; i < num; i++){ ecuria = elems[i]->docsdb; max = 0; if(!criterinit(ecuria) && dpecode != DP_ENOITEM) err = TRUE; while((kbuf = criternext(ecuria, &ksiz)) != NULL){ if(ksiz == sizeof(int)){ if(*(int *)kbuf > max) max = *(int *)kbuf; } free(kbuf); } bases[i] = sum; sum += max; } curia = odeum->indexdb; for(i = 0; i < num; i++){ if(odotcb){ sprintf(otmsg, "merging the inverted index (%d/%d)", i + 1, num); odotcb("odmerge", odeum, otmsg); } ecuria = elems[i]->indexdb; tnum = 0; uend = FALSE; if(!criterinit(ecuria) && dpecode != DP_ENOITEM) err = TRUE; while(!uend){ for(unum = 0; unum < OD_MIWUNIT; unum++){ if(!(word = criternext(ecuria, &wsiz))){ uend = TRUE; break; } if(!(vbuf = crget(ecuria, word, wsiz, 0, -1, &vsiz))){ err = TRUE; free(word); break; } wpunit[unum] = word; wsunit[unum] = wsiz; vpunit[unum] = vbuf; vsunit[unum] = vsiz; } for(j = 0; j < unum; j++){ word = wpunit[j]; wsiz = wsunit[j]; vbuf = vpunit[j]; vsiz = vsunit[j]; pairs = (ODPAIR *)vbuf; pnum = vsiz / sizeof(ODPAIR); for(k = 0; k < pnum; k++){ pairs[k].id += bases[i]; } align = (int)(i < num - 1 ? vsiz * (num - i) * OD_MIARATIO : OD_INDEXALIGN); if(!crsetalign(curia, align)) err = TRUE; if(!crput(curia, word, wsiz, vbuf, vsiz, CR_DCAT)) err = TRUE; free(vbuf); free(word); if(odotcb && (tnum + 1) % OD_OTPERWORDS == 0){ sprintf(otmsg, "... (%d/%d)", tnum + 1, crrnum(ecuria)); odotcb("odmerge", odeum, otmsg); } tnum++; } } } if(odotcb) odotcb("odmerge", odeum, "sorting the inverted index"); tnum = 0; if(!criterinit(curia) && dpecode != DP_ENOITEM) err = TRUE; while((word = criternext(curia, &wsiz)) != NULL){ if((vbuf = crget(curia, word, wsiz, 0, -1, &vsiz)) != NULL){ if(vsiz > sizeof(ODPAIR)){ pairs = (ODPAIR *)vbuf; pnum = vsiz / sizeof(ODPAIR); qsort(pairs, pnum, sizeof(ODPAIR), odsortcompare); if(!crput(curia, word, wsiz, vbuf, vsiz, CR_DOVER)) err = TRUE; } free(vbuf); } free(word); if(odotcb && (tnum + 1) % OD_OTPERWORDS == 0){ sprintf(otmsg, "... (%d/%d)", tnum + 1, crrnum(curia)); odotcb("odmerge", odeum, otmsg); } tnum++; } if(odotcb) odotcb("odmerge", odeum, "synchronizing the inverted index"); if(!crsync(curia)) err = TRUE; dnum = 0; curia = odeum->docsdb; villa = odeum->rdocsdb; for(i = 0; i < num; i++){ if(odotcb){ sprintf(otmsg, "merging the document database (%d/%d)", i + 1, num); odotcb("odmerge", odeum, otmsg); } evilla = elems[i]->rdocsdb; ecuria = elems[i]->docsdb; tnum = 0; if(!vlcurfirst(evilla) && dpecode != DP_ENOITEM) err = TRUE; while(TRUE){ if(!(kbuf = vlcurkey(evilla, &ksiz))) break; if((ksiz == sizeof(OD_DMAXEXPR) && !memcmp(kbuf, OD_DMAXEXPR, ksiz)) || (ksiz == sizeof(OD_DNUMEXPR) && !memcmp(kbuf, OD_DNUMEXPR, ksiz))){ free(kbuf); if(!vlcurnext(evilla)) break; continue; } if(!(vbuf = vlcurval(evilla, &vsiz))){ free(kbuf); if(!vlcurnext(evilla)) break; continue; } if(vsiz != sizeof(int)){ free(vbuf); free(kbuf); if(!vlcurnext(evilla)) break; continue; } id = *(int *)vbuf; nid = id + bases[i]; if(vlput(villa, kbuf, ksiz, (char *)&nid, sizeof(int), VL_DKEEP)){ if((dbuf = crget(ecuria, (char *)&id, sizeof(int), 0, -1, &dsiz)) != NULL){ if(crput(curia, (char *)&nid, sizeof(int), dbuf, dsiz, CR_DKEEP)){ dnum++; } else { err = TRUE; } free(dbuf); } else { err = TRUE; } } else if(dpecode != DP_EKEEP){ err = TRUE; } free(vbuf); free(kbuf); odeum->dnum++; if(odotcb && (tnum + 1) % OD_OTPERDOCS == 0){ sprintf(otmsg, "... (%d/%d)", tnum + 1, crrnum(ecuria)); odotcb("odmerge", odeum, otmsg); } tnum++; if(!vlcurnext(evilla)) break; } } odeum->dnum = dnum; odeum->dmax = dnum; free(bases); if(odotcb) odotcb("odmerge", odeum, "synchronizing the document index"); if(!crsync(curia)) err = TRUE; if(!odclose(odeum)) err = TRUE; for(i = 0; i < num; i++){ if(!odclose(elems[i])) err = TRUE; } free(elems); return err ? FALSE : TRUE; } /* Remove a database directory. */ int odremove(const char *name){ char docsname[OD_PATHBUFSIZ], indexname[OD_PATHBUFSIZ], rdocsname[OD_PATHBUFSIZ]; char path[OD_PATHBUFSIZ]; const char *file; struct stat sbuf; CBLIST *list; int i; assert(name); sprintf(docsname, "%s%c%s", name, MYPATHCHR, OD_DOCSNAME); sprintf(indexname, "%s%c%s", name, MYPATHCHR, OD_INDEXNAME); sprintf(rdocsname, "%s%c%s", name, MYPATHCHR, OD_RDOCSNAME); if(lstat(name, &sbuf) == -1){ dpecodeset(DP_ESTAT, __FILE__, __LINE__); return FALSE; } if(lstat(docsname, &sbuf) != -1 && !crremove(docsname)) return FALSE; if(lstat(indexname, &sbuf) != -1 && !crremove(indexname)) return FALSE; if(lstat(rdocsname, &sbuf) != -1 && !vlremove(rdocsname)) return FALSE; if((list = cbdirlist(name)) != NULL){ for(i = 0; i < cblistnum(list); i++){ file = cblistval(list, i, NULL); if(!strcmp(file, MYCDIRSTR) || !strcmp(file, MYPDIRSTR)) continue; sprintf(path, "%s%c%s", name, MYPATHCHR, file); if(lstat(path, &sbuf) == -1) continue; if(S_ISDIR(sbuf.st_mode)){ if(!crremove(path)) return FALSE; } else { if(!dpremove(path)) return FALSE; } } cblistclose(list); } if(rmdir(name) == -1){ dpecodeset(DP_ERMDIR, __FILE__, __LINE__); return FALSE; } return TRUE; } /* Get a document handle. */ ODDOC *oddocopen(const char *uri){ ODDOC *doc; assert(uri); doc = cbmalloc(sizeof(ODDOC)); doc->id = -1; doc->uri = cbmemdup(uri, -1); doc->attrs = cbmapopenex(OD_MAPPBNUM); doc->nwords = cblistopen(); doc->awords = cblistopen(); return doc; } /* Close a document handle. */ void oddocclose(ODDOC *doc){ assert(doc); cblistclose(doc->awords); cblistclose(doc->nwords); cbmapclose(doc->attrs); free(doc->uri); free(doc); } /* Add an attribute to a document. */ void oddocaddattr(ODDOC *doc, const char *name, const char *value){ assert(doc && name && value); cbmapput(doc->attrs, name, -1, value, -1, TRUE); } /* Add a word to a document. */ void oddocaddword(ODDOC *doc, const char *normal, const char *asis){ assert(doc && normal && asis); cblistpush(doc->nwords, normal, -1); cblistpush(doc->awords, asis, -1); } /* Get the ID number of a document. */ int oddocid(const ODDOC *doc){ assert(doc); return doc->id; } /* Get the URI of a document. */ const char *oddocuri(const ODDOC *doc){ assert(doc); return doc->uri; } /* Get the value of an attribute of a document. */ const char *oddocgetattr(const ODDOC *doc, const char *name){ assert(doc && name); return cbmapget(doc->attrs, name, -1, NULL); } /* Get the list handle contains words in normalized form of a document. */ const CBLIST *oddocnwords(const ODDOC *doc){ assert(doc); return doc->nwords; } /* Get the list handle contains words in appearance form of a document. */ const CBLIST *oddocawords(const ODDOC *doc){ assert(doc); return doc->awords; } /* Get the map handle contains keywords in normalized form and their scores. */ CBMAP *oddocscores(const ODDOC *doc, int max, ODEUM *odeum){ const CBLIST *nwords; CBMAP *map, *kwmap; const char *word, *ctmp; char numbuf[OD_NUMBUFSIZ]; ODWORD *owords; int i, wsiz, wnum, hnum, mnum, nbsiz; double ival; assert(doc && max >= 0); map = cbmapopen(); nwords = oddocnwords(doc); for(i = 0; i < cblistnum(nwords); i++){ word = cblistval(nwords, i, &wsiz); if(wsiz < 1) continue; if((ctmp = cbmapget(map, word, wsiz, NULL)) != NULL){ wnum = *(int *)ctmp + OD_WOCCRPOINT; } else { wnum = OD_WOCCRPOINT; } cbmapput(map, word, wsiz, (char *)&wnum, sizeof(int), TRUE); } mnum = cbmaprnum(map); owords = cbmalloc(mnum * sizeof(ODWORD) + 1); cbmapiterinit(map); for(i = 0; (word = cbmapiternext(map, &wsiz)) != NULL; i++){ owords[i].word = word; owords[i].num = *(int *)cbmapget(map, word, wsiz, NULL); } qsort(owords, mnum, sizeof(ODWORD), odwordcompare); if(odeum){ if(mnum > max * OD_KEYCRATIO) mnum = (int)(max * OD_KEYCRATIO); for(i = 0; i < mnum; i++){ if((hnum = odsearchdnum(odeum, owords[i].word)) < 0) hnum = 0; ival = odlogarithm(hnum); ival = (ival * ival * ival) / 8.0; if(ival < 8.0) ival = 8.0; owords[i].num = (int)(owords[i].num / ival); } qsort(owords, mnum, sizeof(ODWORD), odwordcompare); } if(mnum > max) mnum = max; kwmap = cbmapopenex(OD_MAPPBNUM); for(i = 0; i < mnum; i++){ nbsiz = sprintf(numbuf, "%d", owords[i].num); cbmapput(kwmap, owords[i].word, -1, numbuf, nbsiz, TRUE); } free(owords); cbmapclose(map); return kwmap; } /* Break a text into words in appearance form. */ CBLIST *odbreaktext(const char *text){ const char *word; CBLIST *elems, *words; int i, j, dif, wsiz, pv, delim; assert(text); words = cblistopen(); elems = cbsplit(text, -1, OD_SPACECHARS); for(i = 0; i < cblistnum(elems); i++){ word = cblistval(elems, i, &wsiz); delim = FALSE; j = 0; pv = 0; while(TRUE){ dif = j - pv; if(j >= wsiz){ if(dif > 0 && dif <= OD_MAXWORDLEN) cblistpush(words, word + pv, j - pv); break; } if(delim){ if(!strchr(OD_DELIMCHARS, word[j])){ if(dif > 0 && dif <= OD_MAXWORDLEN) cblistpush(words, word + pv, j - pv); pv = j; delim = FALSE; } } else { if(strchr(OD_DELIMCHARS, word[j])){ if(dif > 0 && dif <= OD_MAXWORDLEN) cblistpush(words, word + pv, j - pv); pv = j; delim = TRUE; } } j++; } } cblistclose(elems); return words; } /* Make the normalized form of a word. */ char *odnormalizeword(const char *asis){ char *nword; int i; assert(asis); for(i = 0; asis[i] != '\0'; i++){ if(!strchr(OD_DELIMCHARS, asis[i])) break; } if(asis[i] == '\0') return cbmemdup("", 0); nword = cbmemdup(asis, -1); for(i = 0; nword[i] != '\0'; i++){ if(nword[i] >= 'A' && nword[i] <= 'Z') nword[i] += 'a' - 'A'; } while(i >= 0){ if(strchr(OD_GLUECHARS, nword[i])){ nword[i] = '\0'; } else { break; } i--; } return nword; } /* Get the common elements of two sets of documents. */ ODPAIR *odpairsand(ODPAIR *apairs, int anum, ODPAIR *bpairs, int bnum, int *np){ CBMAP *map; ODPAIR *result; const char *tmp; int i, rnum; assert(apairs && anum >= 0 && bpairs && bnum >= 0); map = odpairsmap(bpairs, bnum); result = cbmalloc(sizeof(ODPAIR) * anum + 1); rnum = 0; for(i = 0; i < anum; i++){ if(!(tmp = cbmapget(map, (char *)&(apairs[i].id), sizeof(int), NULL))) continue; result[rnum].id = apairs[i].id; result[rnum].score = apairs[i].score + *(int *)tmp; rnum++; } cbmapclose(map); qsort(result, rnum, sizeof(ODPAIR), odsortcompare); *np = rnum; return result; } /* Get the sum of elements of two sets of documents. */ ODPAIR *odpairsor(ODPAIR *apairs, int anum, ODPAIR *bpairs, int bnum, int *np){ CBMAP *map; ODPAIR *result; const char *tmp; int i, score, rnum; assert(apairs && anum >= 0 && bpairs && bnum >= 0); map = odpairsmap(bpairs, bnum); for(i = 0; i < anum; i++){ score = 0; if((tmp = cbmapget(map, (char *)&(apairs[i].id), sizeof(int), NULL)) != NULL) score = *(int *)tmp; score += apairs[i].score; cbmapput(map, (char *)&(apairs[i].id), sizeof(int), (char *)&score, sizeof(int), TRUE); } rnum = cbmaprnum(map); result = cbmalloc(rnum * sizeof(ODPAIR) + 1); cbmapiterinit(map); for(i = 0; (tmp = cbmapiternext(map, NULL)) != NULL; i++){ result[i].id = *(int *)tmp; result[i].score = *(int *)cbmapget(map, tmp, sizeof(int), NULL); } cbmapclose(map); qsort(result, rnum, sizeof(ODPAIR), odsortcompare); *np = rnum; return result; } /* Get the difference set of documents. */ ODPAIR *odpairsnotand(ODPAIR *apairs, int anum, ODPAIR *bpairs, int bnum, int *np){ CBMAP *map; ODPAIR *result; const char *tmp; int i, rnum; assert(apairs && anum >= 0 && bpairs && bnum >= 0); map = odpairsmap(bpairs, bnum); result = cbmalloc(sizeof(ODPAIR) * anum + 1); rnum = 0; for(i = 0; i < anum; i++){ if((tmp = cbmapget(map, (char *)&(apairs[i].id), sizeof(int), NULL)) != NULL) continue; result[rnum].id = apairs[i].id; result[rnum].score = apairs[i].score; rnum++; } cbmapclose(map); qsort(result, rnum, sizeof(ODPAIR), odsortcompare); *np = rnum; return result; } /* Sort a set of documents in descending order of scores. */ void odpairssort(ODPAIR *pairs, int pnum){ assert(pairs && pnum >= 0); qsort(pairs, pnum, sizeof(ODPAIR), odsortcompare); } /* Get the natural logarithm of a number. */ double odlogarithm(double x){ int i; if(x <= 1.0) return 0.0; x = x * x * x * x * x * x * x * x * x * x; for(i = 0; x > 1.0; i++){ x /= 2.718281828459; } return (double)i / 10.0; } /* Get the cosine of the angle of two vectors. */ double odvectorcosine(const int *avec, const int *bvec, int vnum){ double rv; assert(avec && bvec && vnum >= 0); rv = odvecinnerproduct(avec, bvec, vnum) / ((odvecabsolute(avec, vnum) * odvecabsolute(bvec, vnum))); return rv > 0.0 ? rv : 0.0; } /* Set the global tuning parameters. */ void odsettuning(int ibnum, int idnum, int cbnum, int csiz){ if(ibnum > 0) odindexbnum = ibnum; if(idnum > 0) odindexdnum = idnum; if(cbnum > 0) odcachebnum = dpprimenum(cbnum); if(csiz > 0) odcachesiz = csiz; } /* Break a text into words and store appearance forms and normalized form into lists. */ void odanalyzetext(ODEUM *odeum, const char *text, CBLIST *awords, CBLIST *nwords){ char aword[OD_MAXWORDLEN+1], *wp; int lev, wsiz; assert(odeum && text && awords); lev = OD_EVSPACE; wsiz = 0; for(; *text != '\0'; text++){ switch(odeum->statechars[*(unsigned char *)text]){ case OD_EVWORD: if(wsiz > 0 && lev == OD_EVDELIM){ cblistpush(awords, aword, wsiz); if(nwords) cblistpush(nwords, "", 0); wsiz = 0; } if(wsiz <= OD_MAXWORDLEN){ aword[wsiz++] = *text; } lev = OD_EVWORD; break; case OD_EVGLUE: if(wsiz > 0 && lev == OD_EVDELIM){ cblistpush(awords, aword, wsiz); if(nwords) cblistpush(nwords, "", 0); wsiz = 0; } if(wsiz <= OD_MAXWORDLEN){ aword[wsiz++] = *text; } lev = OD_EVGLUE; break; case OD_EVDELIM: if(wsiz > 0 && lev != OD_EVDELIM){ cblistpush(awords, aword, wsiz); if(nwords){ wp = aword; aword[wsiz] = '\0'; while(*wp != '\0'){ if(*wp >= 'A' && *wp <= 'Z') *wp += 'a' - 'A'; wp++; } wp--; while(wp >= aword && odeum->statechars[*(unsigned char *)wp] == OD_EVGLUE){ wsiz--; wp--; } cblistpush(nwords, aword, wsiz); } wsiz = 0; } if(wsiz <= OD_MAXWORDLEN){ aword[wsiz++] = *text; } lev = OD_EVDELIM; break; default: if(wsiz > 0){ cblistpush(awords, aword, wsiz); if(nwords){ if(lev == OD_EVDELIM){ cblistpush(nwords, "", 0); } else { wp = aword; aword[wsiz] = '\0'; while(*wp != '\0'){ if(*wp >= 'A' && *wp <= 'Z') *wp += 'a' - 'A'; wp++; } wp--; while(wp >= aword && odeum->statechars[*(unsigned char *)wp] == OD_EVGLUE){ wsiz--; wp--; } cblistpush(nwords, aword, wsiz); } } wsiz = 0; } lev = OD_EVSPACE; break; } } if(wsiz > 0){ cblistpush(awords, aword, wsiz); if(nwords){ if(lev == OD_EVDELIM){ cblistpush(nwords, "", 0); } else { wp = aword; aword[wsiz] = '\0'; while(*wp != '\0'){ if(*wp >= 'A' && *wp <= 'Z') *wp += 'a' - 'A'; wp++; } wp--; while(wp >= aword && odeum->statechars[*(unsigned char *)wp] == OD_EVGLUE){ wsiz--; wp--; } cblistpush(nwords, aword, wsiz); } } wsiz = 0; } } /* Set the classes of characters used by `odanalyzetext'. */ void odsetcharclass(ODEUM *odeum, const char *spacechars, const char *delimchars, const char *gluechars){ assert(odeum && spacechars && delimchars && gluechars); memset(odeum->statechars, OD_EVWORD, sizeof(odeum->statechars)); for(; *spacechars != '\0'; spacechars++){ odeum->statechars[*(unsigned char *)spacechars] = OD_EVSPACE; } for(; *delimchars != '\0'; delimchars++){ odeum->statechars[*(unsigned char *)delimchars] = OD_EVDELIM; } for(; *gluechars != '\0'; gluechars++){ odeum->statechars[*(unsigned char *)gluechars] = OD_EVGLUE; } } /* Query a database using a small boolean query language. */ ODPAIR *odquery(ODEUM *odeum, const char *query, int *np, CBLIST *errors){ CBLIST *tokens = cblistopen(); CBLIST *nwords = cblistopen(); ODPAIR *results = NULL; assert(odeum && query && np); odanalyzetext(odeum, query, tokens, nwords); odcleannormalized(odeum, nwords); odfixtokens(odeum, tokens); results = odparseexpr(odeum, tokens, nwords, np, errors); cblistclose(tokens); cblistclose(nwords); return results; } /************************************************************************************************* * features for experts *************************************************************************************************/ /* Get the internal database handle for documents. */ CURIA *odidbdocs(ODEUM *odeum){ assert(odeum); return odeum->docsdb; } /* Get the internal database handle for the inverted index. */ CURIA *odidbindex(ODEUM *odeum){ assert(odeum); return odeum->indexdb; } /* Get the internal database handle for the reverse dictionary. */ VILLA *odidbrdocs(ODEUM *odeum){ assert(odeum); return odeum->rdocsdb; } /* Set the call back function called in merging. */ void odsetotcb(void (*otcb)(const char *, ODEUM *, const char *)){ odotcb = otcb; } /* Get the positive one of square roots of a number. */ double odsquareroot(double x){ double c, rv; if(x <= 0.0) return 0.0; c = x > 1.0 ? x : 1; do { rv = c; c = (x / c + c) * 0.5; } while(c < rv); return rv; } /* Get the absolute of a vector. */ double odvecabsolute(const int *vec, int vnum){ double rv; int i; assert(vec && vnum >= 0); rv = 0; for(i = 0; i < vnum; i++){ rv += (double)vec[i] * (double)vec[i]; } return odsquareroot(rv); } /* Get the inner product of two vectors. */ double odvecinnerproduct(const int *avec, const int *bvec, int vnum){ double rv; int i; assert(avec && bvec && vnum >= 0); rv = 0; for(i = 0; i < vnum; i++){ rv += (double)avec[i] * (double)bvec[i]; } return rv; } /************************************************************************************************* * private objects *************************************************************************************************/ /* Get a database handle. `name' specifies the name of a database directory. `omode' specifies the connection mode. `docsbnum` specifies the number of buckets of the document database. `indexbnum` specifies the number of buckets of the index database. `fname' specifies the name of caller function. The return value is the database handle or `NULL' if it is not successful. */ static ODEUM *odopendb(const char *name, int omode, int docsbnum, int indexbnum, const char *fname){ int cromode, vlomode, inode, dmax, dnum; char docsname[OD_PATHBUFSIZ], indexname[OD_PATHBUFSIZ], rdocsname[OD_PATHBUFSIZ], *tmp; struct stat sbuf; CURIA *docsdb, *indexdb; VILLA *rdocsdb; CBMAP *cachemap; CBMAP *sortmap; ODEUM *odeum; assert(name); if(strlen(name) > OD_NAMEMAX){ dpecodeset(DP_EMISC, __FILE__, __LINE__); return NULL; } cromode = CR_OREADER; vlomode = VL_OREADER; if(omode & OD_OWRITER){ cromode = CR_OWRITER; vlomode = VL_OWRITER | VL_OZCOMP | VL_OYCOMP; if(omode & OD_OCREAT){ cromode |= CR_OCREAT; vlomode |= VL_OCREAT; } if(omode & OD_OTRUNC){ cromode |= CR_OTRUNC; vlomode |= VL_OTRUNC; } } if(omode & OD_ONOLCK){ cromode |= CR_ONOLCK; vlomode |= VL_ONOLCK; } if(omode & OD_OLCKNB){ cromode |= CR_OLCKNB; vlomode |= VL_OLCKNB; } sprintf(docsname, "%s%c%s", name, MYPATHCHR, OD_DOCSNAME); sprintf(indexname, "%s%c%s", name, MYPATHCHR, OD_INDEXNAME); sprintf(rdocsname, "%s%c%s", name, MYPATHCHR, OD_RDOCSNAME); docsdb = NULL; indexdb = NULL; rdocsdb = NULL; if((omode & OD_OWRITER) && (omode & OD_OCREAT)){ if(mkdir(name, OD_DIRMODE) == -1 && errno != EEXIST){ dpecodeset(DP_EMKDIR, __FILE__, __LINE__); return NULL; } } if(lstat(name, &sbuf) == -1){ dpecodeset(DP_ESTAT, __FILE__, __LINE__); return NULL; } inode = sbuf.st_ino; if(!(docsdb = cropen(docsname, cromode, docsbnum, OD_DOCSDNUM))) return NULL; if(!(indexdb = cropen(indexname, cromode, indexbnum, odindexdnum))){ crclose(docsdb); return NULL; } if(omode & OD_OWRITER){ if(!crsetalign(docsdb, OD_DOCSALIGN) || !crsetfbpsiz(docsdb, OD_DOCSFBP) || !crsetalign(indexdb, OD_INDEXALIGN) || !crsetfbpsiz(indexdb, OD_INDEXFBP)){ crclose(indexdb); crclose(docsdb); return NULL; } } if(!(rdocsdb = vlopen(rdocsname, vlomode, VL_CMPLEX))){ crclose(indexdb); crclose(docsdb); return NULL; } vlsettuning(rdocsdb, OD_RDOCSLRM, OD_RDOCSNIM, OD_RDOCSLCN, OD_RDOCSNCN); if(omode & OD_OWRITER){ cachemap = cbmapopenex(odcachebnum); sortmap = cbmapopenex(odcachebnum); } else { cachemap = NULL; sortmap = NULL; } if(vlrnum(rdocsdb) > 0){ dmax = -1; dnum = -1; if((tmp = vlget(rdocsdb, OD_DMAXEXPR, sizeof(OD_DMAXEXPR), NULL)) != NULL){ dmax = atoi(tmp); free(tmp); } if((tmp = vlget(rdocsdb, OD_DNUMEXPR, sizeof(OD_DNUMEXPR), NULL)) != NULL){ dnum = atoi(tmp); free(tmp); } if(dmax < 0 || dnum < 0){ if(sortmap) cbmapclose(sortmap); if(cachemap) cbmapclose(cachemap); vlclose(rdocsdb); crclose(indexdb); crclose(docsdb); dpecodeset(DP_EBROKEN, __FILE__, __LINE__); return NULL; } } else { dmax = 0; dnum = 0; } odeum = cbmalloc(sizeof(ODEUM)); odeum->name = cbmemdup(name, -1); odeum->wmode = omode & OD_OWRITER; odeum->fatal = FALSE; odeum->inode = inode; odeum->docsdb = docsdb; odeum->indexdb = indexdb; odeum->rdocsdb = rdocsdb; odeum->cachemap = cachemap; odeum->cacheasiz = 0; odeum->sortmap = sortmap; odeum->dmax = dmax; odeum->dnum = dnum; odeum->ldid = -1; odsetcharclass(odeum, OD_SPACECHARS, OD_DELIMCHARS, OD_GLUECHARS); if(odotcb) odotcb(fname, odeum, "the connection was established"); return odeum; } /* Flush the cache for dirty buffer of words. `odeum' specifies a database handle. `fname' specifies the name of caller function. If successful, the return value is true, else, it is false. */ static int odcacheflush(ODEUM *odeum, const char *fname){ const char *kbuf, *vbuf; char otmsg[OD_OTCBBUFSIZ]; int i, rnum, ksiz, vsiz; assert(odeum); if((rnum = cbmaprnum(odeum->cachemap)) < 1) return TRUE; if(odotcb) odotcb(fname, odeum, "flushing caches"); cbmapiterinit(odeum->cachemap); for(i = 0; (kbuf = cbmapiternext(odeum->cachemap, &ksiz)) != NULL; i++){ vbuf = cbmapget(odeum->cachemap, kbuf, ksiz, &vsiz); if(!crput(odeum->indexdb, kbuf, ksiz, vbuf, vsiz, CR_DCAT)){ odeum->fatal = TRUE; return FALSE; } if(odotcb && (i + 1) % OD_OTPERWORDS == 0){ sprintf(otmsg, "... (%d/%d)", i + 1, rnum); odotcb(fname, odeum, otmsg); } } cbmapclose(odeum->cachemap); odeum->cachemap = cbmapopenex(odcachebnum); odeum->cacheasiz = 0; return TRUE; } /* Flush all frequent words in the cache for dirty buffer of words. `odeum' specifies a database handle. `fname' specifies the name of caller function. `min' specifies the minimum size of frequent words. If successful, the return value is true, else, it is false. */ static int odcacheflushfreq(ODEUM *odeum, const char *fname, int min){ const char *kbuf, *vbuf; char otmsg[OD_OTCBBUFSIZ]; int rnum, ksiz, vsiz; assert(odeum); if((rnum = cbmaprnum(odeum->cachemap)) < 1) return TRUE; if(odotcb){ sprintf(otmsg, "flushing frequent words: min=%d asiz=%d rnum=%d)", min, odeum->cacheasiz, rnum); odotcb(fname, odeum, otmsg); } cbmapiterinit(odeum->cachemap); while((kbuf = cbmapiternext(odeum->cachemap, &ksiz)) != NULL){ vbuf = cbmapget(odeum->cachemap, kbuf, ksiz, &vsiz); if(vsiz >= sizeof(ODPAIR) * min){ if(!crput(odeum->indexdb, kbuf, ksiz, vbuf, vsiz, CR_DCAT)){ odeum->fatal = TRUE; return FALSE; } cbmapout(odeum->cachemap, kbuf, ksiz); odeum->cacheasiz -= vsiz; } } if(odotcb){ sprintf(otmsg, "... (done): min=%d asiz=%d rnum=%d)", min, odeum->cacheasiz, cbmaprnum(odeum->cachemap)); odotcb(fname, odeum, otmsg); } return TRUE; } /* Flush the half of rare words in the cache for dirty buffer of words. `odeum' specifies a database handle. `fname' specifies the name of caller function. `ratio' specifies the ratio of rare words. If successful, the return value is true, else, it is false. */ static int odcacheflushrare(ODEUM *odeum, const char *fname, double ratio){ const char *kbuf, *vbuf; char otmsg[OD_OTCBBUFSIZ]; int i, rnum, limit, ksiz, vsiz; assert(odeum); if((rnum = cbmaprnum(odeum->cachemap)) < 1) return TRUE; if(odotcb){ sprintf(otmsg, "flushing rare words: ratio=%.2f asiz=%d rnum=%d)", ratio, odeum->cacheasiz, rnum); odotcb(fname, odeum, otmsg); } cbmapiterinit(odeum->cachemap); limit = (int)(rnum * ratio); for(i = 0; i < limit && (kbuf = cbmapiternext(odeum->cachemap, &ksiz)) != NULL; i++){ vbuf = cbmapget(odeum->cachemap, kbuf, ksiz, &vsiz); if(!crput(odeum->indexdb, kbuf, ksiz, vbuf, vsiz, CR_DCAT)){ odeum->fatal = TRUE; return FALSE; } cbmapout(odeum->cachemap, kbuf, ksiz); odeum->cacheasiz -= vsiz; } if(odotcb){ sprintf(otmsg, "... (done): ratio=%.2f asiz=%d rnum=%d)", ratio, odeum->cacheasiz, cbmaprnum(odeum->cachemap)); odotcb(fname, odeum, otmsg); } return TRUE; } /* Sort the records of inverted index. `odeum' specifies a database handle. `fname' specifies the name of caller function. If successful, the return value is true, else, it is false. */ static int odsortindex(ODEUM *odeum, const char *fname){ const char *word; char *tmp, otmsg[OD_OTCBBUFSIZ]; int i, rnum, wsiz, tsiz; ODPAIR *pairs; assert(odeum); if((rnum = cbmaprnum(odeum->sortmap)) < 1) return TRUE; if(odotcb) odotcb(fname, odeum, "sorting the inverted index"); cbmapiterinit(odeum->sortmap); for(i = 0; (word = cbmapiternext(odeum->sortmap, &wsiz)) != NULL; i++){ if((tmp = crget(odeum->indexdb, word, wsiz, 0, -1, &tsiz)) != NULL){ if(tsiz > sizeof(ODPAIR)){ pairs = (ODPAIR *)tmp; qsort(pairs, tsiz / sizeof(ODPAIR), sizeof(ODPAIR), odsortcompare); if(!crput(odeum->indexdb, word, wsiz, tmp, tsiz, CR_DOVER)){ free(tmp); return FALSE; } } free(tmp); } else if(dpecode != DP_ENOITEM){ return FALSE; } if(odotcb && (i + 1) % OD_OTPERWORDS == 0){ sprintf(otmsg, "... (%d/%d)", i + 1, rnum); odotcb(fname, odeum, otmsg); } } cbmapclose(odeum->sortmap); odeum->sortmap = cbmapopenex(odcachebnum); return TRUE; } /* Compare two pairs of structures of a search result. `a' specifies the pointer to the region of one pair. `b' specifies the pointer to the region of the other pair. The return value is positive if the former is big, negative if the latter is big, 0 if both are equivalent. */ static int odsortcompare(const void *a, const void *b){ ODPAIR *ap, *bp; int rv; assert(a && b); ap = (ODPAIR *)a; bp = (ODPAIR *)b; rv = bp->score - ap->score; if(rv != 0) return rv; return ap->id - bp->id; } /* Purge the elements of the deleted documents from the inverted index. `odeum' specifies a database handle. `fname' specifies the name of caller function. If successful, the return value is true, else, it is false. */ static int odpurgeindex(ODEUM *odeum, const char *fname){ ODPAIR *pairs; char *kbuf, *vbuf, otmsg[OD_OTCBBUFSIZ]; int i, rnum, tnum, ksiz, vsiz, pnum, wi; assert(odeum); if((rnum = crrnum(odeum->indexdb)) < 1) return TRUE; if(odotcb) odotcb(fname, odeum, "purging dispensable regions"); if(!criterinit(odeum->indexdb)) return FALSE; tnum = 0; while(TRUE){ if(!(kbuf = criternext(odeum->indexdb, &ksiz))){ if(dpecode != DP_ENOITEM) return FALSE; break; } if(!(vbuf = crget(odeum->indexdb, kbuf, ksiz, 0, -1, &vsiz))){ dpecodeset(DP_EBROKEN, __FILE__, __LINE__); free(kbuf); return FALSE; } pairs = (ODPAIR *)vbuf; pnum = vsiz / sizeof(ODPAIR); wi = 0; for(i = 0; i < pnum; i++){ if(crvsiz(odeum->docsdb, (char *)&(pairs[i].id), sizeof(int)) != -1){ pairs[wi++] = pairs[i]; } } if(wi > 0){ if(!crput(odeum->indexdb, kbuf, ksiz, vbuf, wi * sizeof(ODPAIR), CR_DOVER)){ free(vbuf); free(kbuf); return FALSE; } } else { if(!crout(odeum->indexdb, kbuf, ksiz)){ free(vbuf); free(kbuf); return FALSE; } } free(vbuf); free(kbuf); if(odotcb && (tnum + 1) % OD_OTPERWORDS == 0){ sprintf(otmsg, "... (%d/%d)", tnum + 1, rnum); odotcb(fname, odeum, otmsg); } tnum++; } return TRUE; } /* Create a map of a document array. `pairs' specifies the pointer to a document array. `num' specifies the number of elements of the array. The return value is a map of the document array. */ static CBMAP *odpairsmap(const ODPAIR *pairs, int num){ CBMAP *map; int i; assert(pairs && num >= 0); map = cbmapopen(); for(i = 0; i < num; i++){ cbmapput(map, (char *)&(pairs[i].id), sizeof(int), (char *)&(pairs[i].score), sizeof(int), TRUE); } return map; } /* compare two pairs of structures of words in a document. `a' specifies the pointer to the region of one word. `b' specifies the pointer to the region of the other word. The return value is positive if the former is big, negative if the latter is big, 0 if both are equivalent. */ static int odwordcompare(const void *a, const void *b){ ODWORD *ap, *bp; int rv; assert(a && b); ap = (ODWORD *)a; bp = (ODWORD *)b; if((rv = bp->num - ap->num) != 0) return rv; if((rv = strlen(bp->word) - strlen(ap->word)) != 0) return rv; return strcmp(ap->word, bp->word); } /* Match an operator without taking it off the token list. `odeum' specifies a database handle. `tokens' specifies a list handle of tokens. The return value is whether the next token is an operator. */ static int odmatchoperator(ODEUM *odeum, CBLIST *tokens){ const char *tk = NULL; int tk_len = 0; tk = cblistval(tokens, 0, &tk_len); if(tk && (tk[0] == '&' || tk[0] == '|' || tk[0] == '!')) return 1; return 0; } /* Implements the subexpr part of the grammar. `odeum' specifies a database handle. `tokens' specifies a list handle of tokens. `nwords' specifies a list handle of normalized words. `np' specifies the pointer to a variable to which the number of the elements of the return value is assigned. `errors' specifies a list handle into which error messages are stored. The return value is the pointer to an array of document IDs. */ static ODPAIR *odparsesubexpr(ODEUM *odeum, CBLIST *tokens, CBLIST *nwords, int *np, CBLIST *errors){ char *tk = NULL; int tk_len = 0; char *nword = NULL; /* used to do the actual search, should match with tokens */ ODPAIR *result = NULL; int result_num = 0; int i; double ival; if((tk = cblistshift(tokens, &tk_len)) != NULL){ assert(tk != NULL); if(tk[0] == '('){ free(tk); /* recurse into expr */ result = odparseexpr(odeum, tokens, nwords, &result_num, errors); /* match right token RPAREN */ tk = cblistshift(tokens, &tk_len); /* print an error if either we didn't get anything or we didn't get a ) */ if(tk == NULL){ if(errors) cblistpush(errors, "Expression ended without closing ')'", -1); } else if(tk[0] != ')'){ if(errors) cblistpush(errors, "Un-balanced parenthesis.", -1); } } else if(odeum->statechars[*(unsigned char *)tk] == 0){ /* Perform odsearch with the next norm word that isn't an operator. */ nword = cblistshift(nwords, NULL); assert(nword != NULL); if((result = odsearch(odeum, nword, -1, &result_num)) != NULL){ /* TF-IDF tuning */ ival = odlogarithm(result_num); ival = (ival * ival) / 4.0; if(ival < 4.0) ival = 4.0; for(i = 0; i < result_num; i++){ result[i].score = (int)(result[i].score / ival); } } free(nword); } else { if(errors) cblistpush(errors, "Invalid sub-expression. Expected '(' or WORD.", -1); result = cbmalloc(1); result_num = 0; } /* done with the token */ free(tk); } *np = result_num; return result; } /* Implements the actual recursive decent parser for the mini query language. `odeum' specifies a database handle. `tokens' specifies a list handle of tokens. `nwords' specifies a list handle of normalized words. `np' specifies the pointer to a variable to which the number of the elements of the return value is assigned. `errors' specifies a list handle into which error messages are stored. The return value is the pointer to an array of document IDs. It simply parses an initial subexpr, and then loops over as many (operator subexpr) sequences as it can find. The odmatchoperator function handles injecting a default & between consecutive words. */ static ODPAIR *odparseexpr(ODEUM *odeum, CBLIST *tokens, CBLIST *nwords, int *np, CBLIST *errors){ ODPAIR *left = NULL; ODPAIR *right = NULL; ODPAIR *temp = NULL; int left_num = 0; int right_num = 0; int temp_num = 0; char *op = NULL; int op_len = 0; if(!(left = odparsesubexpr(odeum, tokens, nwords, &left_num, errors))) return NULL; /* expr ::= subexpr ( op subexpr )* */ while(odmatchoperator(odeum, tokens)){ op = cblistshift(tokens, &op_len); if(!(right = odparsesubexpr(odeum, tokens, nwords, &right_num, errors))){ free(op); free(left); return NULL; } switch(op[0]){ case '&': temp = odpairsand(left, left_num, right, right_num, &temp_num); break; case '|': temp = odpairsor(left, left_num, right, right_num, &temp_num); break; case '!': temp = odpairsnotand(left, left_num, right, right_num, &temp_num); break; default: if(errors) cblistpush(errors, "Invalid operator. Expected '&', '|', or '!'.", -1); break; } if(temp){ /* an operator was done so we must swap it with the left */ free(left); left = NULL; left = temp; left_num = temp_num; } free(op); if(right) free(right); } *np = left_num; return left; } /* Processes the tokens in order to break them up further. `odeum' specifies a database handle. `tokens' specifies a list handle of tokens. */ static void odfixtokens(ODEUM *odeum, CBLIST *tokens){ const char *tk = NULL; int tk_len = 0; int i = 0; int lastword = 0; for(i = 0; i < cblistnum(tokens); i++){ tk = cblistval(tokens, i, &tk_len); assert(tk); if(tk[0] == '&' || tk[0] == '|' || tk[0] == '!' || tk[0] == '(' || tk[0] == ')'){ lastword = 0; if(tk_len > 1){ /* need to break it up for the next loop around */ tk = cblistremove(tokens, i, &tk_len); cblistinsert(tokens, i, tk, 1); cblistinsert(tokens, i+1, tk+1, tk_len-1); free((char *)tk); } } else if(odeum->statechars[*(unsigned char *)tk] == 0){ /* if the last one was a word and this is a word then we need a default & between them */ if(lastword){ cblistinsert(tokens, i, "&", 1); i++; } lastword = 1; } } } /* Cleans out the parts of the normalized word list that are not considered words. `odeum' specifies a database handle. `tokens' specifies a list handle of tokens. */ static void odcleannormalized(ODEUM *odeum, CBLIST *nwords){ char *tk = NULL; int tk_len = 0; int i = 0; for(i = 0; i < cblistnum(nwords); i++){ tk = (char *)cblistval(nwords, i, &tk_len); if(tk_len == 0 || (!odeum->statechars[*(unsigned char *)tk] == 0)){ /* not a word so delete it */ tk = cblistremove(nwords, i, &tk_len); free(tk); i--; } } } /* END OF FILE */ qdbm-1.8.78/relic.c0000644000175000017500000001665210610627747013032 0ustar mikiomikio/************************************************************************************************* * Implementation of Relic * Copyright (C) 2000-2007 Mikio Hirabayashi * This file is part of QDBM, Quick Database Manager. * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU * Lesser General Public License as published by the Free Software Foundation; either version * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * You should have received a copy of the GNU Lesser General Public License along with QDBM; if * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. *************************************************************************************************/ #define QDBM_INTERNAL 1 #include "relic.h" #include "myconf.h" #define RL_NAMEMAX 512 /* max size of a database name */ #define RL_DIRFSUF MYEXTSTR "dir" /* suffix of a directory file */ #define RL_DATAFSUF MYEXTSTR "pag" /* suffix of a page file */ #define RL_PATHBUFSIZ 1024 /* size of a path buffer */ #define RL_INITBNUM 1913 /* initial bucket number */ #define RL_ALIGNSIZ 16 /* size of alignment */ #define RL_MAXLOAD 1.25 /* max ratio of bucket loading */ #define RL_DIRMAGIC "[depot]\0\v" /* magic number of a directory file */ /* private function prototypes */ static void dbm_writedummy(int fd); static int dbm_writestr(int fd, const char *str); /************************************************************************************************* * public objects *************************************************************************************************/ /* Get a database handle. */ DBM *dbm_open(char *name, int flags, int mode){ DBM *db; DEPOT *depot; int dpomode; char path[RL_PATHBUFSIZ]; int dfd, fd; assert(name); if(strlen(name) > RL_NAMEMAX) return NULL; dpomode = DP_OREADER; if((flags & O_WRONLY) || (flags & O_RDWR)){ dpomode = DP_OWRITER; if(flags & O_CREAT) dpomode |= DP_OCREAT; if(flags & O_TRUNC) dpomode |= DP_OTRUNC; } mode |= 00600; sprintf(path, "%s%s", name, RL_DIRFSUF); if((dfd = open(path, flags, mode)) == -1) return NULL; dbm_writedummy(dfd); sprintf(path, "%s%s", name, RL_DATAFSUF); if((fd = open(path, flags, mode)) == -1 || close(fd) == -1){ close(dfd); return NULL; } if(!(depot = dpopen(path, dpomode, RL_INITBNUM))){ close(dfd); return NULL; } if(dpomode & DP_OWRITER){ if(!dpsetalign(depot, RL_ALIGNSIZ)){ close(dfd); dpclose(depot); return NULL; } } if(!(db = malloc(sizeof(DBM)))){ close(dfd); dpclose(depot); return NULL; } db->depot = depot; db->dfd = dfd; db->dbm_fetch_vbuf = NULL; db->dbm_nextkey_kbuf = NULL; return db; } /* Close a database handle. */ void dbm_close(DBM *db){ assert(db); free(db->dbm_fetch_vbuf); free(db->dbm_nextkey_kbuf); close(db->dfd); dpclose(db->depot); free(db); } /* Store a record. */ int dbm_store(DBM *db, datum key, datum content, int flags){ int dmode; int bnum, rnum; assert(db); if(!key.dptr || key.dsize < 0 || !content.dptr || content.dsize < 0) return -1; dmode = (flags == DBM_INSERT) ? DP_DKEEP : DP_DOVER; if(!dpput(db->depot, key.dptr, key.dsize, content.dptr, content.dsize, dmode)){ if(dpecode == DP_EKEEP) return 1; return -1; } bnum = dpbnum(db->depot); rnum = dprnum(db->depot); if(bnum > 0 && rnum > 0 && ((double)rnum / (double)bnum > RL_MAXLOAD)){ if(!dpoptimize(db->depot, -1)) return -1; } return 0; } /* Delete a record. */ int dbm_delete(DBM *db, datum key){ assert(db); if(!key.dptr || key.dsize < 0) return -1; if(!dpout(db->depot, key.dptr, key.dsize)) return -1; return 0; } /* Retrieve a record. */ datum dbm_fetch(DBM *db, datum key){ datum content; char *vbuf; int vsiz; assert(db); if(!key.dptr || key.dsize < 0 || !(vbuf = dpget(db->depot, key.dptr, key.dsize, 0, -1, &vsiz))){ content.dptr = NULL; content.dsize = 0; return content; } free(db->dbm_fetch_vbuf); db->dbm_fetch_vbuf = vbuf; content.dptr = vbuf; content.dsize = vsiz; return content; } /* Get the first key of a database. */ datum dbm_firstkey(DBM *db){ assert(db); dpiterinit(db->depot); return dbm_nextkey(db); } /* Get the next key of a database. */ datum dbm_nextkey(DBM *db){ datum key; char *kbuf; int ksiz; if(!(kbuf = dpiternext(db->depot, &ksiz))){ key.dptr = NULL; key.dsize = 0; return key; } free(db->dbm_nextkey_kbuf); db->dbm_nextkey_kbuf = kbuf; key.dptr = kbuf; key.dsize = ksiz; return key; } /* Check whether a database has a fatal error or not. */ int dbm_error(DBM *db){ assert(db); return dpfatalerror(db->depot) ? TRUE : FALSE; } /* No effect. */ int dbm_clearerr(DBM *db){ assert(db); return 0; } /* Check whether a handle is read-only or not. */ int dbm_rdonly(DBM *db){ assert(db); return dpwritable(db->depot) ? FALSE : TRUE; } /* Get the file descriptor of a directory file. */ int dbm_dirfno(DBM *db){ assert(db); return db->dfd; } /* Get the file descriptor of a data file. */ int dbm_pagfno(DBM *db){ assert(db); return dpfdesc(db->depot); } /************************************************************************************************* * private objects *************************************************************************************************/ /* Write dummy data into a dummy file. `fd' specifies a file descriptor. */ static void dbm_writedummy(int fd){ struct stat sbuf; if(fstat(fd, &sbuf) == -1 || sbuf.st_size > 0) return; write(fd, RL_DIRMAGIC, sizeof(RL_DIRMAGIC) - 1); dbm_writestr(fd, "\n\n"); dbm_writestr(fd, "\x20\x20\xa2\xca\xa1\xb2\xa2\xca\x20\x20\x20\x20\x20\xa1\xbf\xa1"); dbm_writestr(fd, "\xb1\xa1\xb1\xa1\xb1\xa1\xb1\xa1\xb1\xa1\xb1\xa1\xb1\xa1\xb1\xa1"); dbm_writestr(fd, "\xb1\x0a\xa1\xca\x20\xa1\xad\xa2\xcf\xa1\xae\xa1\xcb\xa1\xe3\x20"); dbm_writestr(fd, "\x20\x4e\x44\x42\x4d\x20\x43\x6f\x6d\x70\x61\x74\x69\x62\x69\x6c"); dbm_writestr(fd, "\x69\x74\x79\x0a\xa1\xca\x20\x20\x20\x20\x20\x20\x20\xa1\xcb\x20"); dbm_writestr(fd, "\x20\xa1\xc0\xa1\xb2\xa1\xb2\xa1\xb2\xa1\xb2\xa1\xb2\xa1\xb2\xa1"); dbm_writestr(fd, "\xb2\xa1\xb2\xa1\xb2\x0a\x20\xa1\xc3\x20\x20\xa1\xc3\x20\xa1\xc3"); dbm_writestr(fd, "\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20"); dbm_writestr(fd, "\x20\x20\x20\x20\x20\x20\x20\x0a\xa1\xca\x5f\x5f\xa1\xb2\xa1\xcb"); dbm_writestr(fd, "\x5f\xa1\xcb\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20"); dbm_writestr(fd, "\x20\x20\x20\x20\x20\x20\x20\x20\x20\x0a"); } /* Write a string into a file. `fd' specifies a file descriptor. `str' specifies a string. */ static int dbm_writestr(int fd, const char *str){ const char *lbuf; int size, rv, wb; assert(fd >= 0 && str); lbuf = str; size = strlen(str); rv = 0; do { wb = write(fd, lbuf, size); switch(wb){ case -1: if(errno != EINTR) return -1; case 0: break; default: lbuf += wb; size -= wb; rv += wb; break; } } while(size > 0); return rv; } /* END OF FILE */ qdbm-1.8.78/NEWS0000644000175000017500000000255310307736130012250 0ustar mikiomikio== Thu, 08 Sep 2005 13:13:58 +0900 == Compressing options of ZLIB was changed. If you use villa with the option `VL_OZCOMP', databases of the earlier versions are not compatible with the current version of QDBM. To convert the old database to new format, export endian independent data by "vlmgr exportdb" with the old version, and then import it by "vlmgr importdb" with the latest version. == Wed, 10 Mar 2004 23:24:24 +0900 == API of B+ tree was changed a bit. Even if you build QDBM with ZLIB enabled, records are not compressed. Instead of it, the function `vlopen' has the option `VL_OZCOMP'. If it is specified, records are compressed. So, you can switch whether to compress records or not, on runtime. Users who have used ZLIB feature should modify their source codes to specify that option. == Wed, 10 Dec 2003 09:24:12 +0900 == The database format was changed with QDBM 1.7.13. Newer versions do not have backward compatibility to old format. You can convert old databases with the command `fmtcnv031127' in the sub directory `lab'. To build it, perform the following steps. cd lab make fmtcnv031127 About usage of it, see the file `README' in `lab'. Typically, to convert a Depot database named as `old' and create a database named as `new', perform the following step. ./fmtcnv031127 < old > new I'm sorry for bothering you. == END OF FILE == qdbm-1.8.78/LTmakefile.in0000644000175000017500000002433610572737610014131 0ustar mikiomikio# Makefile to build QDBM using libtool #================================================================ # Setting variables #================================================================ # Generic settings SHELL = @SHELL@ # Packaging PACKAGE = @PACKAGE_NAME@ VERSION = @PACKAGE_VERSION@ LIBVER = @LIBVER@ LIBREV = @LIBREV@ # Targets MYHEADS = depot.h curia.h relic.h hovel.h cabin.h villa.h vista.h odeum.h MYLIBOBJS = depot.lo curia.lo relic.lo hovel.lo cabin.lo villa.lo vista.lo odeum.lo myconf.lo MYLIBS = libqdbm.la MYBINS = dpmgr dptest dptsv crmgr crtest crtsv rlmgr rltest hvmgr hvtest \ cbtest cbcodec vlmgr vltest vltsv odmgr odtest odidx qmttest MYMAN1S = dpmgr.1 dptest.1 dptsv.1 crmgr.1 crtest.1 crtsv.1 rlmgr.1 rltest.1 hvmgr.1 hvtest.1 \ cbtest.1 cbcodec.1 vlmgr.1 vltest.1 vltsv.1 odmgr.1 odtest.1 odidx.1 qmttest.1 MYMAN3S = qdbm.3 depot.3 dpopen.3 curia.3 cropen.3 relic.3 hovel.3 \ cabin.3 villa.3 vlopen.3 vista.3 odeum.3 odopen.3 MYDOCS = spex.html spex-ja.html COPYING ChangeLog NEWS THANKS MYPCS = qdbm.pc # Install destinations prefix = @prefix@ exec_prefix = @exec_prefix@ MYHEADDIR = @includedir@ MYLIBDIR = @libdir@ MYBINDIR = @bindir@ MYMAN1DIR = @mandir@/man1 MYMAN3DIR = @mandir@/man3 MYSHAREDIR = $(prefix)/share/$(PACKAGE) MYPCDIR = @libdir@/pkgconfig # Building binaries LIBTOOL = libtool CC = gcc CFLAGS = -I. -I$(MYHEADDIR) -I$(HOME)/include -I/usr/local/include @MYDEFS@ \ -D_XOPEN_SOURCE_EXTENDED=1 -D_GNU_SOURCE=1 -D__EXTENSIONS__=1 -D_HPUX_SOURCE=1 \ -D_POSIX_MAPPED_FILES=1 -D_POSIX_SYNCHRONIZED_IO=1 \ -DPIC=1 -D_THREAD_SAFE=1 -D_REENTRANT=1 -DNDEBUG -O3 LD = gcc LIBLDFLAGS = -rpath $(MYLIBDIR) -R $(MYLIBDIR) \ -version-info $$(($(LIBVER)+$(LIBREV))):0:$(LIBREV) @LIBS@ LDFLAGS = -rpath $(MYLIBDIR) -R $(MYLIBDIR) -L. -lqdbm @LIBS@ INSTALL = install MKDIR = mkdir -p CP = cp -rf RM = rm -rf #================================================================ # Suffix rules #================================================================ .SUFFIXES : .SUFFIXES : .c .lo .c.lo : $(LIBTOOL) --mode=compile --tag=CC $(CC) -c $(CFLAGS) $< #================================================================ # Actions #================================================================ all : $(MYLIBS) $(MYBINS) @printf '\n' @printf '#================================================================\n' @printf '# Ready to install.\n' @printf '#================================================================\n' clean : $(RM) $(MYLIBS) $(MYBINS) *.o *.a *.so *.lo *.la a.out .libs \ *.exe *.dll.a *.dll TAGS srcdoc gmon.out leak.log casket casket.* *~ install : $(LIBTOOL) --mode=install $(INSTALL) $(MYHEADS) $(MYHEADDIR) $(LIBTOOL) --mode=install $(INSTALL) $(MYLIBS) $(MYLIBDIR) $(LIBTOOL) --mode=install $(INSTALL) $(MYBINS) $(MYBINDIR) $(MKDIR) $(MYMAN1DIR) cd man && $(CP) $(MYMAN1S) $(MYMAN1DIR) $(MKDIR) $(MYMAN3DIR) cd man && $(CP) $(MYMAN3S) $(MYMAN3DIR) $(MKDIR) $(MYSHAREDIR) $(CP) $(MYDOCS) $(MYSHAREDIR) $(MKDIR) $(MYPCDIR) $(CP) $(MYPCS) $(MYPCDIR) @printf '\n' @printf '#================================================================\n' @printf '# Thanks for using QDBM.\n' @printf '#================================================================\n' uninstall : cd $(MYHEADDIR) && $(LIBTOOL) --mode=uninstall $(RM) $(MYHEADS) cd $(MYLIBDIR) && $(LIBTOOL) --mode=uninstall $(RM) $(MYLIBS) cd $(MYBINDIR) && $(LIBTOOL) --mode=uninstall $(RM) $(MYBINS) cd $(MYMAN1DIR) && $(RM) $(MYMAN1S) cd $(MYMAN3DIR) && $(RM) $(MYMAN3S) $(RM) $(MYSHAREDIR) cd $(MYPCDIR) && $(RM) $(MYPCS) distclean : clean $(RM) Makefile LTmakefile rpmspec config.cache config.log config.status autom4te.cache check : $(RM) casket* $(LIBTOOL) --mode=execute ./dptest write -s casket 500 500000 $(LIBTOOL) --mode=execute ./dptest write casket 50000 5000 $(LIBTOOL) --mode=execute ./dptest read casket $(LIBTOOL) --mode=execute ./dptest read -wb casket $(LIBTOOL) --mode=execute ./dptest rcat -c casket 50000 50 500 32 8 $(LIBTOOL) --mode=execute ./dptest combo casket $(LIBTOOL) --mode=execute ./dptest wicked -c casket 5000 $(LIBTOOL) --mode=execute ./dptest wicked casket 500 $(LIBTOOL) --mode=execute ./dpmgr repair casket $(LIBTOOL) --mode=execute ./dpmgr optimize casket $(LIBTOOL) --mode=execute ./dpmgr list casket $(RM) casket* $(LIBTOOL) --mode=execute ./crtest write -s casket 500 100000 5 $(LIBTOOL) --mode=execute ./crtest write casket 50000 500 10 $(LIBTOOL) --mode=execute ./crtest read casket $(LIBTOOL) --mode=execute ./crtest read -wb casket $(LIBTOOL) --mode=execute ./crtest rcat -c casket 50000 5 10 500 32 8 $(LIBTOOL) --mode=execute ./crtest combo casket $(LIBTOOL) --mode=execute ./crtest wicked -c casket 5000 $(LIBTOOL) --mode=execute ./crtest wicked casket 500 $(LIBTOOL) --mode=execute ./crmgr repair casket $(LIBTOOL) --mode=execute ./crmgr optimize casket $(LIBTOOL) --mode=execute ./crmgr list casket $(RM) casket* $(LIBTOOL) --mode=execute ./crtest write -lob casket 1000 50 10 $(LIBTOOL) --mode=execute ./crtest read -lob casket $(RM) casket* $(LIBTOOL) --mode=execute ./rltest write casket 5000 $(LIBTOOL) --mode=execute ./rltest read casket 5000 $(LIBTOOL) --mode=execute ./rlmgr list casket $(RM) casket* $(LIBTOOL) --mode=execute ./hvtest write casket 5000 $(LIBTOOL) --mode=execute ./hvtest read casket 5000 $(LIBTOOL) --mode=execute ./hvmgr optimize casket $(LIBTOOL) --mode=execute ./hvmgr list casket $(RM) casket* $(LIBTOOL) --mode=execute ./hvtest write -qdbm -s casket 500 $(LIBTOOL) --mode=execute ./hvtest write -qdbm casket 5000 $(LIBTOOL) --mode=execute ./hvtest read -qdbm casket 5000 $(RM) casket* $(LIBTOOL) --mode=execute ./cbtest sort 5000 $(LIBTOOL) --mode=execute ./cbtest strstr 500 $(LIBTOOL) --mode=execute ./cbtest list 50000 $(LIBTOOL) --mode=execute ./cbtest list -d 500 $(LIBTOOL) --mode=execute ./cbtest map 50000 500 $(LIBTOOL) --mode=execute ./cbtest map -d 500 5 $(LIBTOOL) --mode=execute ./cbtest heap 50000 500 $(LIBTOOL) --mode=execute ./cbtest heap -d 500 50 $(LIBTOOL) --mode=execute ./cbtest wicked 5000 $(LIBTOOL) --mode=execute ./cbtest misc $(RM) casket* $(LIBTOOL) --mode=execute ./vltest write -tune 32 31 32 32 casket 50000 $(LIBTOOL) --mode=execute ./vltest read casket $(LIBTOOL) --mode=execute ./vltest rdup -tune 32 31 512 256 casket 50000 50000 $(LIBTOOL) --mode=execute ./vltest combo casket $(LIBTOOL) --mode=execute ./vltest wicked -c casket 5000 $(LIBTOOL) --mode=execute ./vltest wicked casket 500 $(LIBTOOL) --mode=execute ./vlmgr repair casket $(LIBTOOL) --mode=execute ./vlmgr optimize casket $(LIBTOOL) --mode=execute ./vlmgr list casket $(RM) casket* $(LIBTOOL) --mode=execute ./vltest write -int -cz -tune 32 31 32 32 casket 50000 $(LIBTOOL) --mode=execute ./vltest read -int -vc casket $(LIBTOOL) --mode=execute ./vltest rdup -int -cz -cc -tune 32 31 512 256 casket 50000 50000 $(LIBTOOL) --mode=execute ./vltest combo -cz casket $(LIBTOOL) --mode=execute ./vltest wicked -cz -c casket 5000 $(LIBTOOL) --mode=execute ./vltest combo -cy casket $(LIBTOOL) --mode=execute ./vltest wicked -cy -c casket 5000 $(LIBTOOL) --mode=execute ./vltest combo -cx casket $(LIBTOOL) --mode=execute ./vltest wicked -cx -c casket 5000 $(RM) casket* $(LIBTOOL) --mode=execute ./odtest write casket 500 50 5000 $(LIBTOOL) --mode=execute ./odtest read casket $(LIBTOOL) --mode=execute ./odtest combo casket $(LIBTOOL) --mode=execute ./odtest wicked casket 500 $(RM) casket* $(LIBTOOL) --mode=execute ./qmttest casket 50000 10 $(RM) casket* @printf '\n' @printf '#================================================================\n' @printf '# Checking completed.\n' @printf '#================================================================\n' .PHONY : all clean install check #================================================================ # Building binaries #================================================================ libqdbm.la : $(MYLIBOBJS) $(LIBTOOL) --mode=link --tag=CC $(LD) $(MYLIBOBJS) -o $@ $(LIBLDFLAGS) dpmgr : dpmgr.lo $(MYLIBS) $(LIBTOOL) --mode=link --tag=CC $(LD) -o $@ dpmgr.lo $(LDFLAGS) dptest : dptest.lo $(MYLIBS) $(LIBTOOL) --mode=link --tag=CC $(LD) -o $@ dptest.lo $(LDFLAGS) dptsv : dptsv.lo $(MYLIBS) $(LIBTOOL) --mode=link --tag=CC $(LD) -o $@ dptsv.lo $(LDFLAGS) crmgr : crmgr.lo $(MYLIBS) $(LIBTOOL) --mode=link --tag=CC $(LD) -o $@ crmgr.lo $(LDFLAGS) crtest : crtest.lo $(MYLIBS) $(LIBTOOL) --mode=link --tag=CC $(LD) -o $@ crtest.lo $(LDFLAGS) crtsv : crtsv.lo $(MYLIBS) $(LIBTOOL) --mode=link --tag=CC $(LD) -o $@ crtsv.lo $(LDFLAGS) rlmgr : rlmgr.lo $(MYLIBS) $(LIBTOOL) --mode=link --tag=CC $(LD) -o $@ rlmgr.lo $(LDFLAGS) rltest : rltest.lo $(MYLIBS) $(LIBTOOL) --mode=link --tag=CC $(LD) -o $@ rltest.lo $(LDFLAGS) hvmgr : hvmgr.lo $(MYLIBS) $(LIBTOOL) --mode=link --tag=CC $(LD) -o $@ hvmgr.lo $(LDFLAGS) hvtest : hvtest.lo $(MYLIBS) $(LIBTOOL) --mode=link --tag=CC $(LD) -o $@ hvtest.lo $(LDFLAGS) cbtest : cbtest.lo $(MYLIBS) $(LIBTOOL) --mode=link --tag=CC $(LD) -o $@ cbtest.lo $(LDFLAGS) cbcodec : cbcodec.lo $(MYLIBS) $(LIBTOOL) --mode=link --tag=CC $(LD) -o $@ cbcodec.lo $(LDFLAGS) vlmgr : vlmgr.lo $(MYLIBS) $(LIBTOOL) --mode=link --tag=CC $(LD) -o $@ vlmgr.lo $(LDFLAGS) vltest : vltest.lo $(MYLIBS) $(LIBTOOL) --mode=link --tag=CC $(LD) -o $@ vltest.lo $(LDFLAGS) vltsv : vltsv.lo $(MYLIBS) $(LIBTOOL) --mode=link --tag=CC $(LD) -o $@ vltsv.lo $(LDFLAGS) odmgr : odmgr.lo $(MYLIBS) $(LIBTOOL) --mode=link --tag=CC $(LD) -o $@ odmgr.lo $(LDFLAGS) odtest : odtest.lo $(MYLIBS) $(LIBTOOL) --mode=link --tag=CC $(LD) -o $@ odtest.lo $(LDFLAGS) odidx : odidx.lo $(MYLIBS) $(LIBTOOL) --mode=link --tag=CC $(LD) -o $@ odidx.lo $(LDFLAGS) qmttest : qmttest.lo $(MYLIBS) $(LIBTOOL) --mode=link --tag=CC $(LD) -o $@ qmttest.lo $(LDFLAGS) depot.lo dpmgr.lo dptest.lo dptsv.lo : depot.h myconf.h curia.lo crmgr.lo crtest.lo crtsv.lo : curia.h depot.h myconf.h relic.lo rlmgr.lo rltest.lo : relic.h depot.h myconf.h hovel.lo hvmgr.lo hvtest.lo : hovel.h depot.h curia.h myconf.h cabin.lo cbtest.lo : cabin.h myconf.h villa.lo vlmgr.lo vltest.lo vltsv.lo : villa.h depot.h cabin.h myconf.h vista.lo : vista.h villa.h depot.h curia.h cabin.h myconf.h villa.c odeum.lo odmgr.lo odtest.lo odidx.lo : odeum.h depot.h curia.h cabin.h villa.h myconf.h myconf.lo : myconf.h # END OF FILE qdbm-1.8.78/RISCmakefile0000604000175000017500000000651307752161263013737 0ustar mikiomikio# Makefile for the RISC OS version of QDBM # Define which compiler to use: CC = cc #CC = gcc ######################################### # DO NOT EDIT ANYTHING BELOW THIS LINE! # ######################################### ifeq (${CC},cc) CC = cc LD = link AR = libfile DEPEND = -depend !Depend CC_FLAGS = -Wdp -throwback -Otime -I@,Unix: -JUnix UNIXLIB = Unix:o.UnixLib else ifeq (${CC},gcc) CC = gcc LD = gcc AR = ar CC_FLAGS = -mthrowback -O3 -I. else # No other compiler supported! endif endif QDBM_OBJS = o.depot o.curia o.relic o.hovel o.cabin o.villa o.vista o.odeum o.myconf .INIT : @cdir o ## Rule Patterns ## .SUFFIXES : .c .o .c.o : $(CC) $(CC_FLAGS) $(DEPEND) -c -o $@ $< # Static dependencies: all : libqdbm testcases managers converters libqdbm : $(QDBM_OBJS) $(AR) $(AR_FLAGS) -c -o libqdbm $(QDBM_OBJS) testcases : dptest crtest rltest hvtest cbtest vltest odtest create testcases managers : dpmgr crmgr rlmgr hvmgr vlmgr odmgr create managers converters : dptsv crtsv cbcodec vltsv odidx create converters dptest : o.dptest libqdbm $(LD) $(LD_FLAGS) -o $@ o.$* libqdbm $(UNIXLIB) crtest : o.crtest libqdbm $(LD) $(LD_FLAGS) -o $@ o.$* libqdbm $(UNIXLIB) rltest : o.rltest libqdbm $(LD) $(LD_FLAGS) -o $@ o.$* libqdbm $(UNIXLIB) hvtest : o.hvtest libqdbm $(LD) $(LD_FLAGS) -o $@ o.$* libqdbm $(UNIXLIB) cbtest : o.cbtest libqdbm $(LD) $(LD_FLAGS) -o $@ o.$* libqdbm $(UNIXLIB) vltest : o.vltest libqdbm $(LD) $(LD_FLAGS) -o $@ o.$* libqdbm $(UNIXLIB) odtest : o.odtest libqdbm $(LD) $(LD_FLAGS) -o $@ o.$* libqdbm $(UNIXLIB) dpmgr : o.dpmgr libqdbm $(LD) $(LD_FLAGS) -o $@ o.$* libqdbm $(UNIXLIB) crmgr : o.crmgr libqdbm $(LD) $(LD_FLAGS) -o $@ o.$* libqdbm $(UNIXLIB) rlmgr : o.rlmgr libqdbm $(LD) $(LD_FLAGS) -o $@ o.$* libqdbm $(UNIXLIB) hvmgr : o.hvmgr libqdbm $(LD) $(LD_FLAGS) -o $@ o.$* libqdbm $(UNIXLIB) vlmgr : o.vlmgr libqdbm $(LD) $(LD_FLAGS) -o $@ o.$* libqdbm $(UNIXLIB) odmgr : o.odmgr libqdbm $(LD) $(LD_FLAGS) -o $@ o.$* libqdbm $(UNIXLIB) dptsv : o.dptsv libqdbm $(LD) $(LD_FLAGS) -o $@ o.$* libqdbm $(UNIXLIB) crtsv : o.crtsv libqdbm $(LD) $(LD_FLAGS) -o $@ o.$* libqdbm $(UNIXLIB) cbcodec : o.cbcodec libqdbm $(LD) $(LD_FLAGS) -o $@ o.$* libqdbm $(UNIXLIB) vltsv : o.vltsv libqdbm $(LD) $(LD_FLAGS) -o $@ o.$* libqdbm $(UNIXLIB) odidx : o.odidx libqdbm $(LD) $(LD_FLAGS) -o $@ o.$* libqdbm $(UNIXLIB) clean: -ifthere libqdbm then wipe libqdbm ~CFR~V -ifthere dptest then wipe dptest ~CFR~V -ifthere crtest then wipe crtest ~CFR~V -ifthere rltest then wipe rltest ~CFR~V -ifthere hvtest then wipe hvtest ~CFR~V -ifthere cbtest then wipe cbtest ~CFR~V -ifthere vltest then wipe vltest ~CFR~V -ifthere odtest then wipe odtest ~CFR~V -ifthere dpmgr then wipe dpmgr ~CFR~V -ifthere crmgr then wipe crmgr ~CFR~V -ifthere rlmgr then wipe rlmgr ~CFR~V -ifthere hvmgr then wipe hvmgr ~CFR~V -ifthere cbmgr then wipe cbmgr ~CFR~V -ifthere vlmgr then wipe vlmgr ~CFR~V -ifthere odmgr then wipe odmgr ~CFR~V -ifthere dptsv then wipe dptsv ~CFR~V -ifthere crtsv then wipe crtsv ~CFR~V -ifthere cbcodec then wipe cbcodec ~CFR~V -ifthere vltsv then wipe vltsv ~CFR~V -ifthere odidx then wipe odidx ~CFR~V -ifthere testcases then wipe testcases ~CFR~V -ifthere managers then wipe managers ~CFR~V -ifthere converters then wipe converters ~CFR~V -ifthere o.* then wipe o.* ~CFR~V # Dynamic dependencies: qdbm-1.8.78/crmgr.c0000644000175000017500000005347710610627747013054 0ustar mikiomikio/************************************************************************************************* * Utility for debugging Curia and its applications * Copyright (C) 2000-2007 Mikio Hirabayashi * This file is part of QDBM, Quick Database Manager. * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU * Lesser General Public License as published by the Free Software Foundation; either version * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * You should have received a copy of the GNU Lesser General Public License along with QDBM; if * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. *************************************************************************************************/ #include #include #include #include #include #include #undef TRUE #define TRUE 1 /* boolean true */ #undef FALSE #define FALSE 0 /* boolean false */ #define ALIGNSIZ 32 /* basic size of alignment */ /* for RISC OS */ #if defined(__riscos__) || defined(__riscos) #include int __riscosify_control = __RISCOSIFY_NO_PROCESS; #endif /* global variables */ const char *progname; /* program name */ /* function prototypes */ int main(int argc, char **argv); void usage(void); char *hextoobj(const char *str, int *sp); char *dectoiobj(const char *str, int *sp); int runcreate(int argc, char **argv); int runput(int argc, char **argv); int runout(int argc, char **argv); int runget(int argc, char **argv); int runlist(int argc, char **argv); int runoptimize(int argc, char **argv); int runinform(int argc, char **argv); int runremove(int argc, char **argv); int runrepair(int argc, char **argv); int runexportdb(int argc, char **argv); int runimportdb(int argc, char **argv); int runsnaffle(int argc, char **argv); void pdperror(const char *name); void printobj(const char *obj, int size); void printobjhex(const char *obj, int size); int docreate(const char *name, int bnum, int dnum, int sparse); int doput(const char *name, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int dmode, int lob, int align); int doout(const char *name, const char *kbuf, int ksiz, int lob); int doget(const char *name, int opts, const char *kbuf, int ksiz, int start, int max, int ox, int lob, int nb); int dolist(const char *name, int opts, int kb, int vb, int ox); int dooptimize(const char *name, int bnum, int align); int doinform(const char *name, int opts); int doremove(const char *name); int dorepair(const char *name); int doexportdb(const char *name, const char *dir); int doimportdb(const char *name, const char *dir, int bnum, int dnum); int dosnaffle(const char *name, const char *kbuf, int ksiz, int ox, int nb); /* main routine */ int main(int argc, char **argv){ char *env; int rv; cbstdiobin(); progname = argv[0]; if((env = getenv("QDBMDBGFD")) != NULL) dpdbgfd = atoi(env); if(argc < 2) usage(); rv = 0; if(!strcmp(argv[1], "create")){ rv = runcreate(argc, argv); } else if(!strcmp(argv[1], "put")){ rv = runput(argc, argv); } else if(!strcmp(argv[1], "out")){ rv = runout(argc, argv); } else if(!strcmp(argv[1], "get")){ rv = runget(argc, argv); } else if(!strcmp(argv[1], "list")){ rv = runlist(argc, argv); } else if(!strcmp(argv[1], "optimize")){ rv = runoptimize(argc, argv); } else if(!strcmp(argv[1], "inform")){ rv = runinform(argc, argv); } else if(!strcmp(argv[1], "remove")){ rv = runremove(argc, argv); } else if(!strcmp(argv[1], "repair")){ rv = runrepair(argc, argv); } else if(!strcmp(argv[1], "exportdb")){ rv = runexportdb(argc, argv); } else if(!strcmp(argv[1], "importdb")){ rv = runimportdb(argc, argv); } else if(!strcmp(argv[1], "snaffle")){ rv = runsnaffle(argc, argv); } else if(!strcmp(argv[1], "version") || !strcmp(argv[1], "--version")){ printf("Powered by QDBM version %s on %s%s\n", dpversion, dpsysname, dpisreentrant ? " (reentrant)" : ""); printf("Copyright (c) 2000-2007 Mikio Hirabayashi\n"); rv = 0; } else { usage(); } return rv; } /* print the usage and exit */ void usage(void){ fprintf(stderr, "%s: administration utility for Curia\n", progname); fprintf(stderr, "\n"); fprintf(stderr, "usage:\n"); fprintf(stderr, " %s create [-s] [-bnum num] [-dnum num] name\n", progname); fprintf(stderr, " %s put [-kx|-ki] [-vx|-vi|-vf] [-keep|-cat] [-lob] [-na] " "name key val\n", progname); fprintf(stderr, " %s out [-kx|-ki] [-lob] name key\n", progname); fprintf(stderr, " %s get [-nl] [-kx|-ki] [-start num] [-max num] [-ox] [-lob] [-n] name key\n", progname); fprintf(stderr, " %s list [-nl] [-k|-v] [-ox] name\n", progname); fprintf(stderr, " %s optimize [-bnum num] [-na] name\n", progname); fprintf(stderr, " %s inform [-nl] name\n", progname); fprintf(stderr, " %s remove name\n", progname); fprintf(stderr, " %s repair name\n", progname); fprintf(stderr, " %s exportdb name dir\n", progname); fprintf(stderr, " %s importdb [-bnum num] [-dnum num] name dir\n", progname); fprintf(stderr, " %s snaffle [-kx|-ki] [-ox] [-n] name key\n", progname); fprintf(stderr, " %s version\n", progname); fprintf(stderr, "\n"); exit(1); } /* create a binary object from a hexadecimal string */ char *hextoobj(const char *str, int *sp){ char *buf, mbuf[3]; int len, i, j; len = strlen(str); if(!(buf = malloc(len + 1))) return NULL; j = 0; for(i = 0; i < len; i += 2){ while(strchr(" \n\r\t\f\v", str[i])){ i++; } if((mbuf[0] = str[i]) == '\0') break; if((mbuf[1] = str[i+1]) == '\0') break; mbuf[2] = '\0'; buf[j++] = (char)strtol(mbuf, NULL, 16); } buf[j] = '\0'; *sp = j; return buf; } /* create a integer object from a decimal string */ char *dectoiobj(const char *str, int *sp){ char *buf; int num; num = atoi(str); if(!(buf = malloc(sizeof(int)))) return NULL; *(int *)buf = num; *sp = sizeof(int); return buf; } /* parse arguments of create command */ int runcreate(int argc, char **argv){ char *name; int i, sb, bnum, dnum, rv; name = NULL; sb = FALSE; bnum = -1; dnum = -1; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ if(!strcmp(argv[i], "-s")){ sb = TRUE; } else if(!strcmp(argv[i], "-bnum")){ if(++i >= argc) usage(); bnum = atoi(argv[i]); } else if(!strcmp(argv[i], "-dnum")){ if(++i >= argc) usage(); dnum = atoi(argv[i]); } else { usage(); } } else if(!name){ name = argv[i]; } else { usage(); } } if(!name) usage(); rv = docreate(name, bnum, dnum, sb); return rv; } /* parse arguments of put command */ int runput(int argc, char **argv){ char *name, *key, *val, *kbuf, *vbuf; int i, kx, ki, vx, vi, vf, lob, ksiz, vsiz, align, rv; int dmode; name = NULL; kx = FALSE; ki = FALSE; vx = FALSE; vi = FALSE; vf = FALSE; lob = FALSE; align = ALIGNSIZ; key = NULL; val = NULL; dmode = CR_DOVER; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ if(!strcmp(argv[i], "-kx")){ kx = TRUE; } else if(!strcmp(argv[i], "-ki")){ ki = TRUE; } else if(!strcmp(argv[i], "-vx")){ vx = TRUE; } else if(!strcmp(argv[i], "-vi")){ vi = TRUE; } else if(!strcmp(argv[i], "-vf")){ vf = TRUE; } else if(!strcmp(argv[i], "-keep")){ dmode = CR_DKEEP; } else if(!strcmp(argv[i], "-cat")){ dmode = CR_DCAT; } else if(!strcmp(argv[i], "-lob")){ lob = TRUE; } else if(!strcmp(argv[i], "-na")){ align = 0; } else { usage(); } } else if(!name){ name = argv[i]; } else if(!key){ key = argv[i]; } else if(!val){ val = argv[i]; } else { usage(); } } if(!name || !key || !val) usage(); if(kx){ kbuf = hextoobj(key, &ksiz); } else if(ki){ kbuf = dectoiobj(key, &ksiz); } else { kbuf = cbmemdup(key, -1); ksiz = -1; } if(vx){ vbuf = hextoobj(val, &vsiz); } else if(vi){ vbuf = dectoiobj(val, &vsiz); } else if(vf){ vbuf = cbreadfile(val, &vsiz); } else { vbuf = cbmemdup(val, -1); vsiz = -1; } if(kbuf && vbuf){ rv = doput(name, kbuf, ksiz, vbuf, vsiz, dmode, lob, align); } else { if(vf){ fprintf(stderr, "%s: %s: cannot read\n", progname, val); } else { fprintf(stderr, "%s: out of memory\n", progname); } rv = 1; } free(kbuf); free(vbuf); return rv; } /* parse arguments of out command */ int runout(int argc, char **argv){ char *name, *key, *kbuf; int i, kx, ki, lob, ksiz, rv; name = NULL; kx = FALSE; ki = FALSE; lob = FALSE; key = NULL; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ if(!strcmp(argv[i], "-kx")){ kx = TRUE; } else if(!strcmp(argv[i], "-ki")){ ki = TRUE; } else if(!strcmp(argv[i], "-lob")){ lob = TRUE; } else { usage(); } } else if(!name){ name = argv[i]; } else if(!key){ key = argv[i]; } else { usage(); } } if(!name || !key) usage(); if(kx){ kbuf = hextoobj(key, &ksiz); } else if(ki){ kbuf = dectoiobj(key, &ksiz); } else { kbuf = cbmemdup(key, -1); ksiz = -1; } if(kbuf){ rv = doout(name, kbuf, ksiz, lob); } else { fprintf(stderr, "%s: out of memory\n", progname); rv = 1; } free(kbuf); return rv; } /* parse arguments of get command */ int runget(int argc, char **argv){ char *name, *key, *kbuf; int i, opts, kx, ki, ox, lob, nb, start, max, ksiz, rv; name = NULL; opts = 0; kx = FALSE; ki = FALSE; ox = FALSE; lob = FALSE; nb = FALSE; start = 0; max = -1; key = NULL; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ if(!strcmp(argv[i], "-nl")){ opts |= CR_ONOLCK; } else if(!strcmp(argv[i], "-kx")){ kx = TRUE; } else if(!strcmp(argv[i], "-ki")){ ki = TRUE; } else if(!strcmp(argv[i], "-ox")){ ox = TRUE; } else if(!strcmp(argv[i], "-lob")){ lob = TRUE; } else if(!strcmp(argv[i], "-n")){ nb = TRUE; } else if(!strcmp(argv[i], "-start")){ if(++i >= argc) usage(); start = atoi(argv[i]); } else if(!strcmp(argv[i], "-max")){ if(++i >= argc) usage(); max = atoi(argv[i]); } else { usage(); } } else if(!name){ name = argv[i]; } else if(!key){ key = argv[i]; } else { usage(); } } if(!name || !key || start < 0) usage(); if(kx){ kbuf = hextoobj(key, &ksiz); } else if(ki){ kbuf = dectoiobj(key, &ksiz); } else { kbuf = cbmemdup(key, -1); ksiz = -1; } if(kbuf){ rv = doget(name, opts, kbuf, ksiz, start, max, ox, lob, nb); } else { fprintf(stderr, "%s: out of memory\n", progname); rv = 1; } free(kbuf); return rv; } /* parse arguments of list command */ int runlist(int argc, char **argv){ char *name; int i, opts, kb, vb, ox, rv; name = NULL; opts = 0; kb = FALSE; vb = FALSE; ox = FALSE; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ if(!strcmp(argv[i], "-nl")){ opts |= CR_ONOLCK; } else if(!strcmp(argv[i], "-k")){ kb = TRUE; } else if(!strcmp(argv[i], "-v")){ vb = TRUE; } else if(!strcmp(argv[i], "-ox")){ ox = TRUE; } else { usage(); } } else if(!name){ name = argv[i]; } else { usage(); } } if(!name) usage(); rv = dolist(name, opts, kb, vb, ox); return rv; } /* parse arguments of optimize command */ int runoptimize(int argc, char **argv){ char *name; int i, bnum, align, rv; name = NULL; bnum = -1; align = ALIGNSIZ; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ if(!strcmp(argv[i], "-bnum")){ if(++i >= argc) usage(); bnum = atoi(argv[i]); } else if(!strcmp(argv[i], "-na")){ align = 0; } else { usage(); } } else if(!name){ name = argv[i]; } else { usage(); } } if(!name) usage(); rv = dooptimize(name, bnum, align); return rv; } /* parse arguments of inform command */ int runinform(int argc, char **argv){ char *name; int i, opts, rv; name = NULL; opts = 0; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ if(!strcmp(argv[i], "-nl")){ opts |= CR_ONOLCK; } else { usage(); } } else if(!name){ name = argv[i]; } else { usage(); } } if(!name) usage(); rv = doinform(name, opts); return rv; } /* parse arguments of remove command */ int runremove(int argc, char **argv){ char *name; int i, rv; name = NULL; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ usage(); } else if(!name){ name = argv[i]; } else { usage(); } } if(!name) usage(); rv = doremove(name); return rv; } /* parse arguments of repair command */ int runrepair(int argc, char **argv){ char *name; int i, rv; name = NULL; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ usage(); } else if(!name){ name = argv[i]; } else { usage(); } } if(!name) usage(); rv = dorepair(name); return rv; } /* parse arguments of exportdb command */ int runexportdb(int argc, char **argv){ char *name, *dir; int i, rv; name = NULL; dir = NULL; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ usage(); } else if(!name){ name = argv[i]; } else if(!dir){ dir = argv[i]; } else { usage(); } } if(!name || !dir) usage(); rv = doexportdb(name, dir); return rv; } /* parse arguments of importdb command */ int runimportdb(int argc, char **argv){ char *name, *dir; int i, bnum, dnum, rv; name = NULL; dir = NULL; bnum = -1; dnum = -1; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ if(!strcmp(argv[i], "-bnum")){ if(++i >= argc) usage(); bnum = atoi(argv[i]); } else if(!strcmp(argv[i], "-dnum")){ if(++i >= argc) usage(); dnum = atoi(argv[i]); } else { usage(); } } else if(!name){ name = argv[i]; } else if(!dir){ dir = argv[i]; } else { usage(); } } if(!name || !dir) usage(); rv = doimportdb(name, dir, bnum, dnum); return rv; } /* parse arguments of snaffle command */ int runsnaffle(int argc, char **argv){ char *name, *key, *kbuf; int i, kx, ki, ox, nb, start, max, ksiz, rv; name = NULL; kx = FALSE; ki = FALSE; ox = FALSE; nb = FALSE; start = 0; max = -1; key = NULL; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ if(!strcmp(argv[i], "-kx")){ kx = TRUE; } else if(!strcmp(argv[i], "-ki")){ ki = TRUE; } else if(!strcmp(argv[i], "-ox")){ ox = TRUE; } else if(!strcmp(argv[i], "-n")){ nb = TRUE; } else { usage(); } } else if(!name){ name = argv[i]; } else if(!key){ key = argv[i]; } else { usage(); } } if(!name || !key || start < 0) usage(); if(kx){ kbuf = hextoobj(key, &ksiz); } else if(ki){ kbuf = dectoiobj(key, &ksiz); } else { kbuf = cbmemdup(key, -1); ksiz = -1; } if(kbuf){ rv = dosnaffle(name, kbuf, ksiz, ox, nb); } else { fprintf(stderr, "%s: out of memory\n", progname); rv = 1; } free(kbuf); return rv; } /* print an error message */ void pdperror(const char *name){ fprintf(stderr, "%s: %s: %s\n", progname, name, dperrmsg(dpecode)); } /* print an object */ void printobj(const char *obj, int size){ int i; for(i = 0; i < size; i++){ putchar(obj[i]); } } /* print an object as a hexadecimal string */ void printobjhex(const char *obj, int size){ int i; for(i = 0; i < size; i++){ printf("%s%02X", i > 0 ? " " : "", ((const unsigned char *)obj)[i]); } } /* perform create command */ int docreate(const char *name, int bnum, int dnum, int sparse){ CURIA *curia; int omode; omode = CR_OWRITER | CR_OCREAT | CR_OTRUNC | (sparse ? CR_OSPARSE : 0); if(!(curia = cropen(name, omode, bnum, dnum))){ pdperror(name); return 1; } if(!crclose(curia)){ pdperror(name); return 1; } return 0; } /* perform put command */ int doput(const char *name, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int dmode, int lob, int align){ CURIA *curia; if(!(curia = cropen(name, CR_OWRITER, -1, -1))){ pdperror(name); return 1; } if(align > 0 && !crsetalign(curia, ALIGNSIZ)){ pdperror(name); crclose(curia); return 1; } if(lob){ if(!crputlob(curia, kbuf, ksiz, vbuf, vsiz, dmode)){ pdperror(name); crclose(curia); return 1; } } else { if(!crput(curia, kbuf, ksiz, vbuf, vsiz, dmode)){ pdperror(name); crclose(curia); return 1; } } if(!crclose(curia)){ pdperror(name); return 1; } return 0; } /* perform out command */ int doout(const char *name, const char *kbuf, int ksiz, int lob){ CURIA *curia; if(!(curia = cropen(name, CR_OWRITER, -1, -1))){ pdperror(name); return 1; } if(lob){ if(!croutlob(curia, kbuf, ksiz)){ pdperror(name); crclose(curia); return 1; } } else { if(!crout(curia, kbuf, ksiz)){ pdperror(name); crclose(curia); return 1; } } if(!crclose(curia)){ pdperror(name); return 1; } return 0; } /* perform get command */ int doget(const char *name, int opts, const char *kbuf, int ksiz, int start, int max, int ox, int lob, int nb){ CURIA *curia; char *vbuf; int vsiz; if(!(curia = cropen(name, CR_OREADER | opts, -1, -1))){ pdperror(name); return 1; } if(lob){ if(!(vbuf = crgetlob(curia, kbuf, ksiz, start, max, &vsiz))){ pdperror(name); crclose(curia); return 1; } } else { if(!(vbuf = crget(curia, kbuf, ksiz, start, max, &vsiz))){ pdperror(name); crclose(curia); return 1; } } if(ox){ printobjhex(vbuf, vsiz); } else { printobj(vbuf, vsiz); } free(vbuf); if(!nb) putchar('\n'); if(!crclose(curia)){ pdperror(name); return 1; } return 0; } /* perform list command */ int dolist(const char *name, int opts, int kb, int vb, int ox){ CURIA *curia; char *kbuf, *vbuf; int ksiz, vsiz; if(!(curia = cropen(name, CR_OREADER | opts, -1, -1))){ pdperror(name); return 1; } criterinit(curia); while((kbuf = criternext(curia, &ksiz)) != NULL){ if(!(vbuf = crget(curia, kbuf, ksiz, 0, -1, &vsiz))){ pdperror(name); free(kbuf); break; } if(ox){ if(!vb) printobjhex(kbuf, ksiz); if(!kb && !vb) putchar('\t'); if(!kb) printobjhex(vbuf, vsiz); } else { if(!vb) printobj(kbuf, ksiz); if(!kb && !vb) putchar('\t'); if(!kb) printobj(vbuf, vsiz); } putchar('\n'); free(vbuf); free(kbuf); } if(!crclose(curia)){ pdperror(name); return 1; } return 0; } /* perform optimize command */ int dooptimize(const char *name, int bnum, int align){ CURIA *curia; if(!(curia = cropen(name, CR_OWRITER, -1, -1))){ pdperror(name); return 1; } if(align > 0 && !crsetalign(curia, ALIGNSIZ)){ pdperror(name); crclose(curia); return 1; } if(!croptimize(curia, bnum)){ pdperror(name); crclose(curia); return 1; } if(!crclose(curia)){ pdperror(name); return 1; } return 0; } /* perform inform command */ int doinform(const char *name, int opts){ CURIA *curia; if(!(curia = cropen(name, CR_OREADER | opts, -1, -1))){ pdperror(name); return 1; } printf("name: %s\n", crname(curia)); printf("file size: %.0f\n", crfsizd(curia)); printf("all buckets: %d\n", crbnum(curia)); printf("used buckets: %d\n", crbusenum(curia)); printf("records: %d\n", crrnum(curia)); printf("inode number: %d\n", crinode(curia)); printf("modified time: %.0f\n", (double)crmtime(curia)); printf("LOB records: %d\n", crrnumlob(curia)); if(!crclose(curia)){ pdperror(name); return 1; } return 0; } /* perform remove command */ int doremove(const char *name){ if(!crremove(name)){ pdperror(name); return 1; } return 0; } /* perform repair command */ int dorepair(const char *name){ if(!crrepair(name)){ pdperror(name); return 1; } return 0; } /* perform exportdb command */ int doexportdb(const char *name, const char *dir){ CURIA *curia; if(!(curia = cropen(name, CR_OREADER, -1, -1))){ pdperror(name); return 1; } if(!crexportdb(curia, dir)){ pdperror(name); crclose(curia); return 1; } if(!crclose(curia)){ pdperror(name); return 1; } return 0; } /* perform importdb command */ int doimportdb(const char *name, const char *dir, int bnum, int dnum){ CURIA *curia; if(!(curia = cropen(name, CR_OWRITER | CR_OCREAT | CR_OTRUNC, bnum, dnum))){ pdperror(name); return 1; } if(!crimportdb(curia, dir)){ pdperror(name); crclose(curia); return 1; } if(!crclose(curia)){ pdperror(name); return 1; } return 0; } /* perform snaffle command */ int dosnaffle(const char *name, const char *kbuf, int ksiz, int ox, int nb){ char *vbuf; int vsiz; if(!(vbuf = crsnaffle(name, kbuf, ksiz, &vsiz))){ pdperror(name); return 1; } if(ox){ printobjhex(vbuf, vsiz); } else { printobj(vbuf, vsiz); } free(vbuf); if(!nb) putchar('\n'); return 0; } /* END OF FILE */ qdbm-1.8.78/myconf.c0000644000175000017500000006547510610627747013236 0ustar mikiomikio/************************************************************************************************* * Emulation of system calls * Copyright (C) 2000-2007 Mikio Hirabayashi * This file is part of QDBM, Quick Database Manager. * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU * Lesser General Public License as published by the Free Software Foundation; either version * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * You should have received a copy of the GNU Lesser General Public License along with QDBM; if * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. *************************************************************************************************/ #include "myconf.h" /************************************************************************************************* * for dosish filesystems *************************************************************************************************/ #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_) || defined(_SYS_CYGWIN_) #define DOSPATHBUFSIZ 8192 int _qdbm_win32_lstat(const char *pathname, struct stat *buf){ char pbuf[DOSPATHBUFSIZ], *p; int inode; if(stat(pathname, buf) == -1) return -1; if(GetFullPathName(pathname, DOSPATHBUFSIZ, pbuf, &p) != 0){ inode = 11003; for(p = pbuf; *p != '\0'; p++){ inode = inode * 31 + *(unsigned char *)p; } buf->st_ino = (inode * 911) & 0x7FFF; } return 0; } #endif /************************************************************************************************* * for POSIX thread *************************************************************************************************/ #if defined(MYPTHREAD) #include #define PTKEYMAX 8 struct { void *ptr; pthread_key_t key; } _qdbm_ptkeys[PTKEYMAX]; int _qdbm_ptknum = 0; static void *_qdbm_gettsd(void *ptr, int size, const void *initval); void *_qdbm_settsd(void *ptr, int size, const void *initval){ static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; char *val; if((val = _qdbm_gettsd(ptr, size, initval)) != NULL) return val; if(pthread_mutex_lock(&mutex) != 0) return NULL; if((val = _qdbm_gettsd(ptr, size, initval)) != NULL){ pthread_mutex_unlock(&mutex); return val; } if(_qdbm_ptknum >= PTKEYMAX){ pthread_mutex_unlock(&mutex); return NULL; } _qdbm_ptkeys[_qdbm_ptknum].ptr = ptr; if(pthread_key_create(&(_qdbm_ptkeys[_qdbm_ptknum].key), free) != 0){ pthread_mutex_unlock(&mutex); return NULL; } if(!(val = malloc(size))){ pthread_key_delete(_qdbm_ptkeys[_qdbm_ptknum].key); pthread_mutex_unlock(&mutex); return NULL; } memcpy(val, initval, size); if(pthread_setspecific(_qdbm_ptkeys[_qdbm_ptknum].key, val) != 0){ free(val); pthread_key_delete(_qdbm_ptkeys[_qdbm_ptknum].key); pthread_mutex_unlock(&mutex); return NULL; } _qdbm_ptknum++; pthread_mutex_unlock(&mutex); return val; } static void *_qdbm_gettsd(void *ptr, int size, const void *initval){ char *val; int i; for(i = 0; i < _qdbm_ptknum; i++){ if(_qdbm_ptkeys[i].ptr == ptr){ if(!(val = pthread_getspecific(_qdbm_ptkeys[i].key))){ if(!(val = malloc(size))) return NULL; memcpy(val, initval, size); if(pthread_setspecific(_qdbm_ptkeys[i].key, val) != 0){ free(val); return NULL; } } return val; } } return NULL; } #endif /************************************************************************************************* * for systems without mmap *************************************************************************************************/ #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_) #define MMFDESCMAX 2048 struct { void *start; HANDLE handle; } mmhandles[MMFDESCMAX]; int mmhnum = 0; CRITICAL_SECTION mmcsec; static void _qdbm_delete_mmap_env(void); void *_qdbm_mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset){ static volatile long first = TRUE; static volatile long ready = FALSE; HANDLE handle; int i; if(InterlockedExchange((void *)&first, FALSE)){ InitializeCriticalSection(&mmcsec); atexit(_qdbm_delete_mmap_env); InterlockedExchange((void *)&ready, TRUE); } while(!InterlockedCompareExchange((void *)&ready, TRUE, TRUE)){ Sleep(1); } if(fd < 0 || flags & MAP_FIXED) return MAP_FAILED; if(!(handle = CreateFileMapping((HANDLE)_get_osfhandle(fd), NULL, (prot & PROT_WRITE) ? PAGE_READWRITE : PAGE_READONLY, 0, length, NULL))) return MAP_FAILED; if(!(start = MapViewOfFile(handle, (prot & PROT_WRITE) ? FILE_MAP_WRITE : FILE_MAP_READ, 0, 0, length))){ CloseHandle(handle); return MAP_FAILED; } EnterCriticalSection(&mmcsec); if(mmhnum >= MMFDESCMAX - 1){ UnmapViewOfFile(start); CloseHandle(handle); LeaveCriticalSection(&mmcsec); return MAP_FAILED; } for(i = 0; i < MMFDESCMAX; i++){ if(!mmhandles[i].start){ mmhandles[i].start = start; mmhandles[i].handle = handle; break; } } mmhnum++; LeaveCriticalSection(&mmcsec); return start; } int _qdbm_munmap(void *start, size_t length){ HANDLE handle; int i; EnterCriticalSection(&mmcsec); handle = NULL; for(i = 0; i < MMFDESCMAX; i++){ if(mmhandles[i].start == start){ handle = mmhandles[i].handle; mmhandles[i].start = NULL; mmhandles[i].handle = NULL; break; } } if(!handle){ LeaveCriticalSection(&mmcsec); return -1; } mmhnum--; LeaveCriticalSection(&mmcsec); if(!UnmapViewOfFile(start)){ CloseHandle(handle); return -1; } if(!CloseHandle(handle)) return -1; return 0; } int _qdbm_msync(const void *start, size_t length, int flags){ if(!FlushViewOfFile(start, length)) return -1; return 0; } static void _qdbm_delete_mmap_env(void){ DeleteCriticalSection(&mmcsec); } #elif defined(_SYS_FREEBSD_) || defined(_SYS_NETBSD_) || defined(_SYS_OPENBSD_) || \ defined(_SYS_AIX_) || defined(_SYS_RISCOS_) || defined(MYNOMMAP) void *_qdbm_mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset){ char *buf, *wp; int rv, rlen; if(flags & MAP_FIXED) return MAP_FAILED; if(lseek(fd, SEEK_SET, offset) == -1) return MAP_FAILED; if(!(buf = malloc(sizeof(int) * 3 + length))) return MAP_FAILED; wp = buf; *(int *)wp = fd; wp += sizeof(int); *(int *)wp = offset; wp += sizeof(int); *(int *)wp = prot; wp += sizeof(int); rlen = 0; while((rv = read(fd, wp + rlen, length - rlen)) > 0){ rlen += rv; } if(rv == -1 || rlen != length){ free(buf); return MAP_FAILED; } return wp; } int _qdbm_munmap(void *start, size_t length){ char *buf, *rp; int fd, offset, prot, rv, wlen; buf = (char *)start - sizeof(int) * 3; rp = buf; fd = *(int *)rp; rp += sizeof(int); offset = *(int *)rp; rp += sizeof(int); prot = *(int *)rp; rp += sizeof(int); if(prot & PROT_WRITE){ if(lseek(fd, offset, SEEK_SET) == -1){ free(buf); return -1; } wlen = 0; while(wlen < (int)length){ rv = write(fd, rp + wlen, length - wlen); if(rv == -1){ if(errno == EINTR) continue; free(buf); return -1; } wlen += rv; } } free(buf); return 0; } int _qdbm_msync(const void *start, size_t length, int flags){ char *buf, *rp; int fd, offset, prot, rv, wlen; buf = (char *)start - sizeof(int) * 3; rp = buf; fd = *(int *)rp; rp += sizeof(int); offset = *(int *)rp; rp += sizeof(int); prot = *(int *)rp; rp += sizeof(int); if(prot & PROT_WRITE){ if(lseek(fd, offset, SEEK_SET) == -1) return -1; wlen = 0; while(wlen < (int)length){ rv = write(fd, rp + wlen, length - wlen); if(rv == -1){ if(errno == EINTR) continue; return -1; } wlen += rv; } } return 0; } #endif /************************************************************************************************* * for reentrant time routines *************************************************************************************************/ #if defined(_SYS_LINUX_) || defined(_SYS_FREEBSD_) || defined(_SYS_OPENBSD_) || \ defined(_SYS_NETBSD_) || defined(_SYS_SUNOS_) || defined(_SYS_HPUX_) || \ defined(_SYS_MACOSX_) || defined(_SYS_CYGWIN_) struct tm *_qdbm_gmtime(const time_t *timep, struct tm *result){ return gmtime_r(timep, result); } struct tm *_qdbm_localtime(const time_t *timep, struct tm *result){ return localtime_r(timep, result); } # else struct tm *_qdbm_gmtime(const time_t *timep, struct tm *result){ return gmtime(timep); } struct tm *_qdbm_localtime(const time_t *timep, struct tm *result){ return localtime(timep); } # endif /************************************************************************************************* * for systems without times *************************************************************************************************/ #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_) clock_t _qdbm_times(struct tms *buf){ buf->tms_utime = clock(); buf->tms_stime = 0; buf->tms_cutime = 0; buf->tms_cstime = 0; return 0; } #endif /************************************************************************************************* * for Win32 *************************************************************************************************/ #if defined(_SYS_MSVC_) || defined(_SYS_MINGW_) #define WINLOCKWAIT 100 int _qdbm_win32_fcntl(int fd, int cmd, struct flock *lock){ HANDLE fh; DWORD opt; OVERLAPPED ol; fh = (HANDLE)_get_osfhandle(fd); opt = (cmd == F_SETLK) ? LOCKFILE_FAIL_IMMEDIATELY : 0; if(lock->l_type == F_WRLCK) opt |= LOCKFILE_EXCLUSIVE_LOCK; memset(&ol, 0, sizeof(OVERLAPPED)); ol.Offset = INT_MAX; ol.OffsetHigh = 0; ol.hEvent = 0; if(!LockFileEx(fh, opt, 0, 1, 0, &ol)){ if(GetLastError() == ERROR_CALL_NOT_IMPLEMENTED){ while(TRUE){ if(LockFile(fh, 0, 0, 1, 0)) return 0; Sleep(WINLOCKWAIT); } } return -1; } return 0; } #endif #if defined(_SYS_MSVC_) DIR *_qdbm_win32_opendir(const char *name){ char expr[8192]; int len; DIR *dir; HANDLE fh; WIN32_FIND_DATA data; len = strlen(name); if(len > 0 && name[len-1] == MYPATHCHR){ sprintf(expr, "%s*", name); } else { sprintf(expr, "%s%c*", name, MYPATHCHR); } if((fh = FindFirstFile(expr, &data)) == INVALID_HANDLE_VALUE) return NULL; if(!(dir = malloc(sizeof(DIR)))){ FindClose(fh); return NULL; } dir->fh = fh; dir->data = data; dir->first = TRUE; return dir; } int _qdbm_win32_closedir(DIR *dir){ if(!FindClose(dir->fh)){ free(dir); return -1; } free(dir); return 0; } struct dirent *_qdbm_win32_readdir(DIR *dir){ if(dir->first){ sprintf(dir->de.d_name, "%s", dir->data.cFileName); dir->first = FALSE; return &(dir->de); } if(!FindNextFile(dir->fh, &(dir->data))) return NULL; sprintf(dir->de.d_name, "%s", dir->data.cFileName); return &(dir->de); } #endif /************************************************************************************************* * for checking information of the system *************************************************************************************************/ #if defined(_SYS_LINUX_) int _qdbm_vmemavail(size_t size){ char buf[4096], *rp; int fd, rv, bsiz; double avail; if((fd = open("/proc/meminfo", O_RDONLY, 00644)) == -1) return TRUE; rv = TRUE; if((bsiz = read(fd, buf, sizeof(buf) - 1)) > 0){ buf[bsiz] = '\0'; avail = -1; if((rp = strstr(buf, "MemFree:")) != NULL){ rp = strchr(rp, ':') + 1; avail = strtod(rp, NULL) * 1024.0; if((rp = strstr(buf, "SwapFree:")) != NULL){ rp = strchr(rp, ':') + 1; avail += strtod(rp, NULL) * 1024.0; } if(size >= avail) rv = FALSE; } } close(fd); return rv; } #elif defined(_SYS_MSVC_) || defined(_SYS_MINGW_) || defined(_SYS_CYGWIN_) int _qdbm_vmemavail(size_t size){ MEMORYSTATUS sbuf; sbuf.dwLength = sizeof(MEMORYSTATUS); GlobalMemoryStatus(&sbuf); return size < sbuf.dwAvailVirtual; } #else int _qdbm_vmemavail(size_t size){ return TRUE; } #endif /************************************************************************************************* * for ZLIB *************************************************************************************************/ #if defined(MYZLIB) #include #define ZLIBBUFSIZ 8192 static char *_qdbm_deflate_impl(const char *ptr, int size, int *sp, int mode); static char *_qdbm_inflate_impl(const char *ptr, int size, int *sp, int mode); static unsigned int _qdbm_getcrc_impl(const char *ptr, int size); char *(*_qdbm_deflate)(const char *, int, int *, int) = _qdbm_deflate_impl; char *(*_qdbm_inflate)(const char *, int, int *, int) = _qdbm_inflate_impl; unsigned int (*_qdbm_getcrc)(const char *, int) = _qdbm_getcrc_impl; static char *_qdbm_deflate_impl(const char *ptr, int size, int *sp, int mode){ z_stream zs; char *buf, *swap; unsigned char obuf[ZLIBBUFSIZ]; int rv, asiz, bsiz, osiz; if(size < 0) size = strlen(ptr); zs.zalloc = Z_NULL; zs.zfree = Z_NULL; zs.opaque = Z_NULL; switch(mode){ case _QDBM_ZMRAW: if(deflateInit2(&zs, 5, Z_DEFLATED, -15, 7, Z_DEFAULT_STRATEGY) != Z_OK) return NULL; break; case _QDBM_ZMGZIP: if(deflateInit2(&zs, 6, Z_DEFLATED, 15 + 16, 9, Z_DEFAULT_STRATEGY) != Z_OK) return NULL; break; default: if(deflateInit2(&zs, 6, Z_DEFLATED, 15, 8, Z_DEFAULT_STRATEGY) != Z_OK) return NULL; break; } asiz = size + 16; if(asiz < ZLIBBUFSIZ) asiz = ZLIBBUFSIZ; if(!(buf = malloc(asiz))){ deflateEnd(&zs); return NULL; } bsiz = 0; zs.next_in = (unsigned char *)ptr; zs.avail_in = size; zs.next_out = obuf; zs.avail_out = ZLIBBUFSIZ; while((rv = deflate(&zs, Z_FINISH)) == Z_OK){ osiz = ZLIBBUFSIZ - zs.avail_out; if(bsiz + osiz > asiz){ asiz = asiz * 2 + osiz; if(!(swap = realloc(buf, asiz))){ free(buf); deflateEnd(&zs); return NULL; } buf = swap; } memcpy(buf + bsiz, obuf, osiz); bsiz += osiz; zs.next_out = obuf; zs.avail_out = ZLIBBUFSIZ; } if(rv != Z_STREAM_END){ free(buf); deflateEnd(&zs); return NULL; } osiz = ZLIBBUFSIZ - zs.avail_out; if(bsiz + osiz + 1 > asiz){ asiz = asiz * 2 + osiz; if(!(swap = realloc(buf, asiz))){ free(buf); deflateEnd(&zs); return NULL; } buf = swap; } memcpy(buf + bsiz, obuf, osiz); bsiz += osiz; buf[bsiz] = '\0'; if(mode == _QDBM_ZMRAW) bsiz++; *sp = bsiz; deflateEnd(&zs); return buf; } static char *_qdbm_inflate_impl(const char *ptr, int size, int *sp, int mode){ z_stream zs; char *buf, *swap; unsigned char obuf[ZLIBBUFSIZ]; int rv, asiz, bsiz, osiz; zs.zalloc = Z_NULL; zs.zfree = Z_NULL; zs.opaque = Z_NULL; switch(mode){ case _QDBM_ZMRAW: if(inflateInit2(&zs, -15) != Z_OK) return NULL; break; case _QDBM_ZMGZIP: if(inflateInit2(&zs, 15 + 16) != Z_OK) return NULL; break; default: if(inflateInit2(&zs, 15) != Z_OK) return NULL; break; } asiz = size * 2 + 16; if(asiz < ZLIBBUFSIZ) asiz = ZLIBBUFSIZ; if(!(buf = malloc(asiz))){ inflateEnd(&zs); return NULL; } bsiz = 0; zs.next_in = (unsigned char *)ptr; zs.avail_in = size; zs.next_out = obuf; zs.avail_out = ZLIBBUFSIZ; while((rv = inflate(&zs, Z_NO_FLUSH)) == Z_OK){ osiz = ZLIBBUFSIZ - zs.avail_out; if(bsiz + osiz >= asiz){ asiz = asiz * 2 + osiz; if(!(swap = realloc(buf, asiz))){ free(buf); inflateEnd(&zs); return NULL; } buf = swap; } memcpy(buf + bsiz, obuf, osiz); bsiz += osiz; zs.next_out = obuf; zs.avail_out = ZLIBBUFSIZ; } if(rv != Z_STREAM_END){ free(buf); inflateEnd(&zs); return NULL; } osiz = ZLIBBUFSIZ - zs.avail_out; if(bsiz + osiz >= asiz){ asiz = asiz * 2 + osiz; if(!(swap = realloc(buf, asiz))){ free(buf); inflateEnd(&zs); return NULL; } buf = swap; } memcpy(buf + bsiz, obuf, osiz); bsiz += osiz; buf[bsiz] = '\0'; if(sp) *sp = bsiz; inflateEnd(&zs); return buf; } static unsigned int _qdbm_getcrc_impl(const char *ptr, int size){ int crc; if(size < 0) size = strlen(ptr); crc = crc32(0, Z_NULL, 0); return crc32(crc, (unsigned char *)ptr, size); } #else char *(*_qdbm_deflate)(const char *, int, int *, int) = NULL; char *(*_qdbm_inflate)(const char *, int, int *, int) = NULL; unsigned int (*_qdbm_getcrc)(const char *, int) = NULL; #endif /************************************************************************************************* * for LZO *************************************************************************************************/ #if defined(MYLZO) #include static char *_qdbm_lzoencode_impl(const char *ptr, int size, int *sp); static char *_qdbm_lzodecode_impl(const char *ptr, int size, int *sp); int _qdbm_lzo_init = FALSE; char *(*_qdbm_lzoencode)(const char *, int, int *) = _qdbm_lzoencode_impl; char *(*_qdbm_lzodecode)(const char *, int, int *) = _qdbm_lzodecode_impl; static char *_qdbm_lzoencode_impl(const char *ptr, int size, int *sp){ char wrkmem[LZO1X_1_MEM_COMPRESS]; lzo_bytep buf; lzo_uint bsiz; if(!_qdbm_lzo_init){ if(lzo_init() != LZO_E_OK) return NULL; _qdbm_lzo_init = TRUE; } if(size < 0) size = strlen(ptr); if(!(buf = malloc(size + size / 16 + 80))) return NULL; if(lzo1x_1_compress((lzo_bytep)ptr, size, buf, &bsiz, wrkmem) != LZO_E_OK){ free(buf); return NULL; } buf[bsiz] = '\0'; *sp = bsiz; return (char *)buf; } static char *_qdbm_lzodecode_impl(const char *ptr, int size, int *sp){ lzo_bytep buf; lzo_uint bsiz; int rat, rv; if(!_qdbm_lzo_init){ if(lzo_init() != LZO_E_OK) return NULL; _qdbm_lzo_init = TRUE; } rat = 6; while(TRUE){ bsiz = (size + 256) * rat + 3; if(!(buf = malloc(bsiz + 1))) return NULL; rv = lzo1x_decompress_safe((lzo_bytep)(ptr), size, buf, &bsiz, NULL); if(rv == LZO_E_OK){ break; } else if(rv == LZO_E_OUTPUT_OVERRUN){ free(buf); rat *= 2; } else { free(buf); return NULL; } } buf[bsiz] = '\0'; if(sp) *sp = bsiz; return (char *)buf; } #else char *(*_qdbm_lzoencode)(const char *, int, int *) = NULL; char *(*_qdbm_lzodecode)(const char *, int, int *) = NULL; #endif /************************************************************************************************* * for BZIP2 *************************************************************************************************/ #if defined(MYBZIP) #include #define BZIPBUFSIZ 8192 static char *_qdbm_bzencode_impl(const char *ptr, int size, int *sp); static char *_qdbm_bzdecode_impl(const char *ptr, int size, int *sp); char *(*_qdbm_bzencode)(const char *, int, int *) = _qdbm_bzencode_impl; char *(*_qdbm_bzdecode)(const char *, int, int *) = _qdbm_bzdecode_impl; static char *_qdbm_bzencode_impl(const char *ptr, int size, int *sp){ bz_stream zs; char *buf, *swap, obuf[BZIPBUFSIZ]; int rv, asiz, bsiz, osiz; if(size < 0) size = strlen(ptr); zs.bzalloc = NULL; zs.bzfree = NULL; zs.opaque = NULL; if(BZ2_bzCompressInit(&zs, 9, 0, 30) != BZ_OK) return NULL; asiz = size + 16; if(asiz < BZIPBUFSIZ) asiz = BZIPBUFSIZ; if(!(buf = malloc(asiz))){ BZ2_bzCompressEnd(&zs); return NULL; } bsiz = 0; zs.next_in = (char *)ptr; zs.avail_in = size; zs.next_out = obuf; zs.avail_out = BZIPBUFSIZ; while((rv = BZ2_bzCompress(&zs, BZ_FINISH)) == BZ_FINISH_OK){ osiz = BZIPBUFSIZ - zs.avail_out; if(bsiz + osiz > asiz){ asiz = asiz * 2 + osiz; if(!(swap = realloc(buf, asiz))){ free(buf); BZ2_bzCompressEnd(&zs); return NULL; } buf = swap; } memcpy(buf + bsiz, obuf, osiz); bsiz += osiz; zs.next_out = obuf; zs.avail_out = BZIPBUFSIZ; } if(rv != BZ_STREAM_END){ free(buf); BZ2_bzCompressEnd(&zs); return NULL; } osiz = BZIPBUFSIZ - zs.avail_out; if(bsiz + osiz + 1 > asiz){ asiz = asiz * 2 + osiz; if(!(swap = realloc(buf, asiz))){ free(buf); BZ2_bzCompressEnd(&zs); return NULL; } buf = swap; } memcpy(buf + bsiz, obuf, osiz); bsiz += osiz; buf[bsiz] = '\0'; *sp = bsiz; BZ2_bzCompressEnd(&zs); return buf; } static char *_qdbm_bzdecode_impl(const char *ptr, int size, int *sp){ bz_stream zs; char *buf, *swap, obuf[BZIPBUFSIZ]; int rv, asiz, bsiz, osiz; zs.bzalloc = NULL; zs.bzfree = NULL; zs.opaque = NULL; if(BZ2_bzDecompressInit(&zs, 0, 0) != BZ_OK) return NULL; asiz = size * 2 + 16; if(asiz < BZIPBUFSIZ) asiz = BZIPBUFSIZ; if(!(buf = malloc(asiz))){ BZ2_bzDecompressEnd(&zs); return NULL; } bsiz = 0; zs.next_in = (char *)ptr; zs.avail_in = size; zs.next_out = obuf; zs.avail_out = BZIPBUFSIZ; while((rv = BZ2_bzDecompress(&zs)) == BZ_OK){ osiz = BZIPBUFSIZ - zs.avail_out; if(bsiz + osiz >= asiz){ asiz = asiz * 2 + osiz; if(!(swap = realloc(buf, asiz))){ free(buf); BZ2_bzDecompressEnd(&zs); return NULL; } buf = swap; } memcpy(buf + bsiz, obuf, osiz); bsiz += osiz; zs.next_out = obuf; zs.avail_out = BZIPBUFSIZ; } if(rv != BZ_STREAM_END){ free(buf); BZ2_bzDecompressEnd(&zs); return NULL; } osiz = BZIPBUFSIZ - zs.avail_out; if(bsiz + osiz >= asiz){ asiz = asiz * 2 + osiz; if(!(swap = realloc(buf, asiz))){ free(buf); BZ2_bzDecompressEnd(&zs); return NULL; } buf = swap; } memcpy(buf + bsiz, obuf, osiz); bsiz += osiz; buf[bsiz] = '\0'; if(sp) *sp = bsiz; BZ2_bzDecompressEnd(&zs); return buf; } #else char *(*_qdbm_bzencode)(const char *, int, int *) = NULL; char *(*_qdbm_bzdecode)(const char *, int, int *) = NULL; #endif /************************************************************************************************* * for ICONV *************************************************************************************************/ #if defined(MYICONV) #include #define ICONVCHECKSIZ 32768 #define ICONVMISSMAX 256 #define ICONVALLWRAT 0.001 static char *_qdbm_iconv_impl(const char *ptr, int size, const char *icode, const char *ocode, int *sp, int *mp); static const char *_qdbm_encname_impl(const char *ptr, int size); static int _qdbm_encmiss(const char *ptr, int size, const char *icode, const char *ocode); char *(*_qdbm_iconv)(const char *, int, const char *, const char *, int *, int *) = _qdbm_iconv_impl; const char *(*_qdbm_encname)(const char *, int) = _qdbm_encname_impl; static char *_qdbm_iconv_impl(const char *ptr, int size, const char *icode, const char *ocode, int *sp, int *mp){ iconv_t ic; char *obuf, *wp, *rp; size_t isiz, osiz; int miss; if(size < 0) size = strlen(ptr); isiz = size; if((ic = iconv_open(ocode, icode)) == (iconv_t)-1) return NULL; osiz = isiz * 5; if(!(obuf = malloc(osiz + 1))){ iconv_close(ic); return NULL; } wp = obuf; rp = (char *)ptr; miss = 0; while(isiz > 0){ if(iconv(ic, (void *)&rp, &isiz, &wp, &osiz) == -1){ if(errno == EILSEQ && (*rp == 0x5c || *rp == 0x7e)){ *wp = *rp; wp++; rp++; isiz--; } else if(errno == EILSEQ || errno == EINVAL){ rp++; isiz--; miss++; } else { break; } } } *wp = '\0'; if(iconv_close(ic) == -1){ free(obuf); return NULL; } if(sp) *sp = wp - obuf; if(mp) *mp = miss; return obuf; } static const char *_qdbm_encname_impl(const char *ptr, int size){ const char *hypo; int i, miss, cr; if(size < 0) size = strlen(ptr); if(size > ICONVCHECKSIZ) size = ICONVCHECKSIZ; if(size >= 2 && (!memcmp(ptr, "\xfe\xff", 2) || !memcmp(ptr, "\xff\xfe", 2))) return "UTF-16"; for(i = 0; i < size - 1; i += 2){ if(ptr[i] == 0 && ptr[i+1] != 0) return "UTF-16BE"; if(ptr[i+1] == 0 && ptr[i] != 0) return "UTF-16LE"; } for(i = 0; i < size - 3; i++){ if(ptr[i] == 0x1b){ i++; if(ptr[i] == '(' && strchr("BJHI", ptr[i+1])) return "ISO-2022-JP"; if(ptr[i] == '$' && strchr("@B(", ptr[i+1])) return "ISO-2022-JP"; } } if(_qdbm_encmiss(ptr, size, "US-ASCII", "UTF-16BE") < 1) return "US-ASCII"; if(_qdbm_encmiss(ptr, size, "UTF-8", "UTF-16BE") < 1) return "UTF-8"; hypo = NULL; cr = FALSE; for(i = 0; i < size; i++){ if(ptr[i] == 0xd){ cr = TRUE; break; } } if(cr){ if((miss = _qdbm_encmiss(ptr, size, "Shift_JIS", "EUC-JP")) < 1) return "Shift_JIS"; if(!hypo && miss / (double)size <= ICONVALLWRAT) hypo = "Shift_JIS"; if((miss = _qdbm_encmiss(ptr, size, "EUC-JP", "UTF-16BE")) < 1) return "EUC-JP"; if(!hypo && miss / (double)size <= ICONVALLWRAT) hypo = "EUC-JP"; } else { if((miss = _qdbm_encmiss(ptr, size, "EUC-JP", "UTF-16BE")) < 1) return "EUC-JP"; if(!hypo && miss / (double)size <= ICONVALLWRAT) hypo = "EUC-JP"; if((miss = _qdbm_encmiss(ptr, size, "Shift_JIS", "EUC-JP")) < 1) return "Shift_JIS"; if(!hypo && miss / (double)size <= ICONVALLWRAT) hypo = "Shift_JIS"; } if((miss = _qdbm_encmiss(ptr, size, "UTF-8", "UTF-16BE")) < 1) return "UTF-8"; if(!hypo && miss / (double)size <= ICONVALLWRAT) hypo = "UTF-8"; if((miss = _qdbm_encmiss(ptr, size, "CP932", "UTF-16BE")) < 1) return "CP932"; if(!hypo && miss / (double)size <= ICONVALLWRAT) hypo = "CP932"; return hypo ? hypo : "ISO-8859-1"; } static int _qdbm_encmiss(const char *ptr, int size, const char *icode, const char *ocode){ iconv_t ic; char obuf[ICONVCHECKSIZ], *wp, *rp; size_t isiz, osiz; int miss; isiz = size; if((ic = iconv_open(ocode, icode)) == (iconv_t)-1) return ICONVMISSMAX; miss = 0; rp = (char *)ptr; while(isiz > 0){ osiz = ICONVCHECKSIZ; wp = obuf; if(iconv(ic, (void *)&rp, &isiz, &wp, &osiz) == -1){ if(errno == EILSEQ || errno == EINVAL){ rp++; isiz--; miss++; if(miss >= ICONVMISSMAX) break; } else { break; } } } if(iconv_close(ic) == -1) return ICONVMISSMAX; return miss; } #else char *(*_qdbm_iconv)(const char *, int, const char *, const char *, int *, int *) = NULL; const char *(*_qdbm_encname)(const char *, int) = NULL; #endif /************************************************************************************************* * common settings *************************************************************************************************/ int _qdbm_dummyfunc(void){ return 0; } /* END OF FILE */ qdbm-1.8.78/COPYING0000644000175000017500000006347607324302233012615 0ustar mikiomikio GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! qdbm-1.8.78/THANKS0000644000175000017500000000176110356022315012461 0ustar mikiomikio================================================================ Thanks to all of the following for their valuable suggestions or contributions. ================================================================ Kang-Jin Lee - suggestions about the GDBM-compatible API - contributions about Makefile Pat Podenski - suggestions about porting to Mac OS X, Solaris, and HP-UX BERO - contributions about supporting MinGW Stefan Bellon - contributions about porting to RISC OS Donald Gobin - contributions about supporting Visual C++ Emanuel Dejanu - contributions about supporting Visual C++ Keith Bostic - suggestions about the performance test suite William Lachance - contributions about RPM spec file Zed A. Shaw - contributions about a text analyzer in Odeum - contributions about a query language in Odeum Chris Bilderback - contributions about cursor functions in Villa. Fumitoshi Ukai - contributions of troff manuals - making Debian packages == END OF FILE == qdbm-1.8.78/qdbm.pc.in0000644000175000017500000000045710255772244013436 0ustar mikiomikioprefix=@prefix@ exec_prefix=@exec_prefix@ bindir=@bindir@ libdir=@libdir@ libexecdir=@libexecdir@ includedir=@includedir@ datadir=@datadir@ Name: QDBM Description: a high performance embedded database library Version: @PACKAGE_VERSION@ Requires: Libs: -L${libdir} -lqdbm @LIBS@ Cflags: -I${includedir} qdbm-1.8.78/VCmakefile0000644000175000017500000001727710357712064013520 0ustar mikiomikio# Makefile to build QDBM using Microsoft Visual C++ #================================================================ # Setting variables #================================================================ # VC++ directory VCPATH = C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7 # User options YOUR_CLFLAGS = YOUR_LIBFLAGS = YOUR_LINKFLAGS= # Configurations !IF "$(CFG)" == "ld" !MESSAGE Build using static debug configuration BASE_FLAGS = /MLd /W3 /ZI /Od /FD /GZ /Fo"$(OUTDIR)\\" /Fd"$(OUTDIR)\\" BASE_DEFS = /D_DEBUG /D__DEBUG__ OUTDIR = .\tmp_ld LIB_APPEND = _ld EXE_APPEND = _ld !ELSEIF "$(CFG)" == "l" !MESSAGE Build using static release configuration BASE_DEFS = /DNDEBUG BASE_FLAGS = /ML /W3 /O2 /FD /Fo"$(OUTDIR)\\" /Fd"$(OUTDIR)\\" OUTDIR = .\tmp_l LIB_APPEND = _l EXE_APPEND = _l !ELSEIF "$(CFG)" == "td" !MESSAGE Build using static threaded debug configuration BASE_FLAGS = /MTd /W3 /ZI /Od /FD /GZ /Fo"$(OUTDIR)\\" /Fd"$(OUTDIR)\\" BASE_DEFS = /D_DEBUG /D__DEBUG__ OUTDIR = .\tmp_td LIB_APPEND = _td EXE_APPEND = _td !ELSEIF "$(CFG)" == "t" !MESSAGE Build using static threaded release configuration BASE_DEFS = /DNDEBUG BASE_FLAGS = /MT /W3 /O2 /FD /Fo"$(OUTDIR)\\" /Fd"$(OUTDIR)\\" OUTDIR = .\tmp_t LIB_APPEND = _t EXE_APPEND = _t !ELSEIF "$(CFG)" == "dd" !MESSAGE Build using dynamic threaded debug configuration BASE_FLAGS = /MDd /W3 /ZI /Od /FD /GZ /Fo"$(OUTDIR)\\" /Fd"$(OUTDIR)\\" BASE_DEFS = /D_DEBUG /D__DEBUG__ OUTDIR = .\tmp_dd LIB_APPEND = _dd EXE_APPEND = _dd !ELSE !MESSAGE Build using dynamic threaded release configuration BASE_DEFS = /DNDEBUG BASE_FLAGS = /MD /W3 /O2 /FD /Fo"$(OUTDIR)\\" /Fd"$(OUTDIR)\\" OUTDIR = .\tmp LIB_APPEND = EXE_APPEND = !ENDIF # Building binaries CLFLAGS = /I "$(VCPATH)\Include" /I "$(VCPATH)\PlatformSDK\Include" /I "." \ /nologo $(YOUR_CLFLAGS) $(BASE_FLAGS) $(BASE_DEFS) /D_CRT_SECURE_NO_DEPRECATE=1 LIBFLAGS = /libpath:"$(VCPATH)\lib" /libpath:"$(VCPATH)\PlatformSDK\Lib" /libpath:"." \ /nologo $(YOUR_LIBFLAGS) LINKFLAGS = /libpath:"$(VCPATH)\lib" /libpath:"$(VCPATH)\PlatformSDK\Lib" /libpath:"." \ /nologo $(YOUR_LINKFLAGS) # Targets MYLIBS = qdbm$(LIB_APPEND).dll qdbm$(LIB_APPEND).lib qdbm$(LIB_APPEND)_static.lib LIBOBJS = $(OUTDIR)\depot.obj $(OUTDIR)\curia.obj $(OUTDIR)\relic.obj \ $(OUTDIR)\hovel.obj $(OUTDIR)\cabin.obj $(OUTDIR)\villa.obj \ $(OUTDIR)\vista.obj $(OUTDIR)\odeum.obj $(OUTDIR)\myconf.obj MYBINS = dpmgr$(EXE_APPEND).exe dptest$(EXE_APPEND).exe dptsv$(EXE_APPEND).exe \ crmgr$(EXE_APPEND).exe crtest$(EXE_APPEND).exe crtsv$(EXE_APPEND).exe \ rlmgr$(EXE_APPEND).exe rltest$(EXE_APPEND).exe hvmgr$(EXE_APPEND).exe \ hvtest$(EXE_APPEND).exe cbtest$(EXE_APPEND).exe cbcodec$(EXE_APPEND).exe \ vlmgr$(EXE_APPEND).exe vltest$(EXE_APPEND).exe vltsv$(EXE_APPEND).exe \ odmgr$(EXE_APPEND).exe odtest$(EXE_APPEND).exe odidx$(EXE_APPEND).exe #================================================================ # Suffix rules #================================================================ .SUFFIXES : .SUFFIXES : .c .obj .c{$(OUTDIR)}.obj : cl /c $(CLFLAGS) $< .c.obj: cl /c $(CLFLAGS) $< #================================================================ # Actions #================================================================ all : $(OUTDIR) $(MYLIBS) $(MYBINS) allcfg: nmake /NOLOGO /f VCmakefile CFG=ld nmake /NOLOGO /f VCmakefile CFG=l nmake /NOLOGO /f VCmakefile CFG=td nmake /NOLOGO /f VCmakefile CFG=t nmake /NOLOGO /f VCmakefile CFG=dd nmake /NOLOGO /f VCmakefile clean : -rd tmp_ld /S /Q > NUL: 2>&1 -rd tmp_l /S /Q > NUL: 2>&1 -rd tmp_td /S /Q > NUL: 2>&1 -rd tmp_t /S /Q > NUL: 2>&1 -rd tmp_dd /S /Q > NUL: 2>&1 -rd tmp /S /Q > NUL: 2>&1 -del *.obj *.lib *.dll *.exp *.exe casket /F /Q > NUL: 2>&1 "$(OUTDIR)" : if not exist "$(OUTDIR)/" mkdir "$(OUTDIR)" #================================================================ # Building binaries #================================================================ qdbm$(LIB_APPEND).dll : $(LIBOBJS) qdbm.def link /DLL /DEF:qdbm.def $(LINKFLAGS) /OUT:$@ /IMPLIB:qdbm$(LIB_APPEND).lib $(LIBOBJS) qdbm$(LIB_APPEND).lib : qdbm$(LIB_APPEND).dll qdbm$(LIB_APPEND)_static.lib : $(LIBOBJS) lib $(LIBFLAGS) /OUT:$@ $(LIBOBJS) dpmgr$(EXE_APPEND).exe : $(OUTDIR)\dpmgr.obj qdbm$(LIB_APPEND).lib link $(LINKFLAGS) /OUT:$@ $(OUTDIR)\dpmgr.obj qdbm$(LIB_APPEND).lib dptest$(EXE_APPEND).exe : $(OUTDIR)\dptest.obj qdbm$(LIB_APPEND).lib link $(LINKFLAGS) /OUT:$@ $(OUTDIR)\dptest.obj qdbm$(LIB_APPEND).lib dptsv$(EXE_APPEND).exe : $(OUTDIR)\dptsv.obj qdbm$(LIB_APPEND).lib link $(LINKFLAGS) /OUT:$@ $(OUTDIR)\dptsv.obj qdbm$(LIB_APPEND).lib crmgr$(EXE_APPEND).exe : $(OUTDIR)\crmgr.obj qdbm$(LIB_APPEND).lib link $(LINKFLAGS) /OUT:$@ $(OUTDIR)\crmgr.obj qdbm$(LIB_APPEND).lib crtest$(EXE_APPEND).exe : $(OUTDIR)\crtest.obj qdbm$(LIB_APPEND).lib link $(LINKFLAGS) /OUT:$@ $(OUTDIR)\crtest.obj qdbm$(LIB_APPEND).lib crtsv$(EXE_APPEND).exe : $(OUTDIR)\crtsv.obj qdbm$(LIB_APPEND).lib link $(LINKFLAGS) /OUT:$@ $(OUTDIR)\crtsv.obj qdbm$(LIB_APPEND).lib rlmgr$(EXE_APPEND).exe : $(OUTDIR)\rlmgr.obj qdbm$(LIB_APPEND).lib link $(LINKFLAGS) /OUT:$@ $(OUTDIR)\rlmgr.obj qdbm$(LIB_APPEND).lib rltest$(EXE_APPEND).exe : $(OUTDIR)\rltest.obj qdbm$(LIB_APPEND).lib link $(LINKFLAGS) /OUT:$@ $(OUTDIR)\rltest.obj qdbm$(LIB_APPEND).lib hvmgr$(EXE_APPEND).exe : $(OUTDIR)\hvmgr.obj qdbm$(LIB_APPEND).lib link $(LINKFLAGS) /OUT:$@ $(OUTDIR)\hvmgr.obj qdbm$(LIB_APPEND).lib hvtest$(EXE_APPEND).exe : $(OUTDIR)\hvtest.obj qdbm$(LIB_APPEND).lib link $(LINKFLAGS) /OUT:$@ $(OUTDIR)\hvtest.obj qdbm$(LIB_APPEND).lib cbtest$(EXE_APPEND).exe : $(OUTDIR)\cbtest.obj qdbm$(LIB_APPEND).lib link $(LINKFLAGS) /OUT:$@ $(OUTDIR)\cbtest.obj qdbm$(LIB_APPEND).lib cbcodec$(EXE_APPEND).exe : $(OUTDIR)\cbcodec.obj qdbm$(LIB_APPEND).lib link $(LINKFLAGS) /OUT:$@ $(OUTDIR)\cbcodec.obj qdbm$(LIB_APPEND).lib vlmgr$(EXE_APPEND).exe : $(OUTDIR)\vlmgr.obj qdbm$(LIB_APPEND).lib link $(LINKFLAGS) /OUT:$@ $(OUTDIR)\vlmgr.obj qdbm$(LIB_APPEND).lib vltest$(EXE_APPEND).exe : $(OUTDIR)\vltest.obj qdbm$(LIB_APPEND).lib link $(LINKFLAGS) /OUT:$@ $(OUTDIR)\vltest.obj qdbm$(LIB_APPEND).lib vltsv$(EXE_APPEND).exe : $(OUTDIR)\vltsv.obj qdbm$(LIB_APPEND).lib link $(LINKFLAGS) /OUT:$@ $(OUTDIR)\vltsv.obj qdbm$(LIB_APPEND).lib odmgr$(EXE_APPEND).exe : $(OUTDIR)\odmgr.obj qdbm$(LIB_APPEND).lib link $(LINKFLAGS) /OUT:$@ $(OUTDIR)\odmgr.obj qdbm$(LIB_APPEND).lib odtest$(EXE_APPEND).exe : $(OUTDIR)\odtest.obj qdbm$(LIB_APPEND).lib link $(LINKFLAGS) /OUT:$@ $(OUTDIR)\odtest.obj qdbm$(LIB_APPEND).lib odidx$(EXE_APPEND).exe : $(OUTDIR)\odidx.obj qdbm$(LIB_APPEND).lib link $(LINKFLAGS) /OUT:$@ $(OUTDIR)\odidx.obj qdbm$(LIB_APPEND).lib $(OUTDIR)\depot.obj $(OUTDIR)\dpmgr.obj $(OUTDIR)\dptest.obj $(OUTDIR)\dptsv.obj : \ depot.h myconf.h $(OUTDIR)\curia.obj $(OUTDIR)\crmgr.obj $(OUTDIR)\crtest.obj $(OUTDIR)\crtsv.obj : \ curia.h depot.h myconf.h $(OUTDIR)\relic.obj $(OUTDIR)\rlmgr.obj $(OUTDIR)\rltest.obj : \ relic.h depot.h myconf.h $(OUTDIR)\hovel.obj $(OUTDIR)\hvmgr.obj $(OUTDIR)\hvtest.obj : \ hovel.h depot.h curia.h myconf.h $(OUTDIR)\cabin.obj $(OUTDIR)\cbtest.obj $(OUTDIR)\cbcodec.obj : \ cabin.h myconf.h $(OUTDIR)\villa.obj $(OUTDIR)\vlmgr.obj $(OUTDIR)\vltest.obj $(OUTDIR)\vltsv.obj : \ villa.h depot.h cabin.h myconf.h $(OUTDIR)\vista.obj : vista.h villa.h depot.h curia.h cabin.h myconf.h $(OUTDIR)\odeum.obj $(OUTDIR)\odmgr.obj $(OUTDIR)\odtest.obj $(OUTDIR)\odidx.obj : \ odeum.h depot.h curia.h cabin.h villa.h myconf.h $(OUTDIR)\myconf.obj : myconf.h # END OF FILE qdbm-1.8.78/bros/0000755000175000017500000000000010523136343012511 5ustar mikiomikioqdbm-1.8.78/bros/gdbmtest.c0000644000175000017500000001205310355663555014504 0ustar mikiomikio/************************************************************************************************* * Writing test of GNU Database Manager *************************************************************************************************/ #include #include #include #include #undef TRUE #define TRUE 1 /* boolean true */ #undef FALSE #define FALSE 0 /* boolean false */ #define RECBUFSIZ 32 /* buffer for records */ #define CACHESIZE 16 /* cache size */ /* global variables */ const char *progname; /* program name */ int showprgr; /* whether to show progression */ /* function prototypes */ int main(int argc, char **argv); void usage(void); int runwrite(int argc, char **argv); int runread(int argc, char **argv); int dowrite(char *name, int rnum); int doread(char *name, int rnum); /* main routine */ int main(int argc, char **argv){ int rv; progname = argv[0]; showprgr = TRUE; if(getenv("HIDEPRGR")) showprgr = FALSE; if(argc < 2) usage(); rv = 0; if(!strcmp(argv[1], "write")){ rv = runwrite(argc, argv); } else if(!strcmp(argv[1], "read")){ rv = runread(argc, argv); } else { usage(); } return rv; } /* print the usage and exit */ void usage(void){ fprintf(stderr, "%s: test cases for GNU Database Manager\n", progname); fprintf(stderr, "\n"); fprintf(stderr, "usage:\n"); fprintf(stderr, " %s write name rnum\n", progname); fprintf(stderr, " %s read name rnum\n", progname); fprintf(stderr, "\n"); exit(1); } /* parse arguments of write command */ int runwrite(int argc, char **argv){ char *name, *rstr; int i, rnum, rv; name = NULL; rstr = NULL; rnum = 0; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ usage(); } else if(!name){ name = argv[i]; } else if(!rstr){ rstr = argv[i]; } else { usage(); } } if(!name || !rstr) usage(); rnum = atoi(rstr); if(rnum < 1) usage(); rv = dowrite(name, rnum); return rv; } /* parse arguments of read command */ int runread(int argc, char **argv){ char *name, *rstr; int i, rnum, rv; name = NULL; rstr = NULL; rnum = 0; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ usage(); } else if(!name){ name = argv[i]; } else if(!rstr){ rstr = argv[i]; } else { usage(); } } if(!name || !rstr) usage(); rnum = atoi(rstr); if(rnum < 1) usage(); rv = doread(name, rnum); return rv; } /* perform write command */ int dowrite(char *name, int rnum){ GDBM_FILE dbf; datum key, content; int i, err, optval, len; char buf[RECBUFSIZ]; if(showprgr) printf("\n name=%s rnum=%d\n\n", name, rnum); /* open a database */ if(!(dbf = gdbm_open(name, 0, GDBM_NEWDB, 00644, NULL))){ fprintf(stderr, "gdbm_open failed\n"); return 1; } optval = CACHESIZE; if(gdbm_setopt(dbf, GDBM_CACHESIZE, &optval, sizeof(int)) != 0){ fprintf(stderr, "gdbm_setopt failed\n"); gdbm_close(dbf); return 1; } err = FALSE; /* loop for each record */ for(i = 1; i <= rnum; i++){ len = sprintf(buf, "%08d", i); key.dptr = buf; key.dsize = len; content.dptr = buf; content.dsize = len; /* store a record */ if(gdbm_store(dbf, key, content, GDBM_REPLACE) != 0){ fprintf(stderr, "gdbm_store failed\n"); err = TRUE; break; } /* print progression */ if(showprgr && rnum > 250 && i % (rnum / 250) == 0){ putchar('.'); fflush(stdout); if(i == rnum || i % (rnum / 10) == 0){ printf(" (%08d)\n", i); fflush(stdout); } } } /* close the database */ gdbm_close(dbf); if(showprgr && !err) printf("ok\n\n"); return err ? 1 : 0; } /* perform read command */ int doread(char *name, int rnum){ GDBM_FILE dbf; datum key, content; int i, err, optval, len; char buf[RECBUFSIZ]; if(showprgr) printf("\n name=%s rnum=%d\n\n", name, rnum); /* open a database */ if(!(dbf = gdbm_open(name, 0, GDBM_READER, 00644, NULL))){ fprintf(stderr, "gdbm_open failed\n"); return 1; } optval = CACHESIZE; if(gdbm_setopt(dbf, GDBM_CACHESIZE, &optval, sizeof(int)) != 0){ fprintf(stderr, "gdbm_setopt failed\n"); gdbm_close(dbf); return 1; } err = FALSE; /* loop for each record */ for(i = 1; i <= rnum; i++){ /* retrieve a record */ len = sprintf(buf, "%08d", i); key.dptr = buf; key.dsize = len; content = gdbm_fetch(dbf, key); if(!content.dptr){ fprintf(stderr, "gdbm_fetch failed\n"); err = TRUE; break; } free(content.dptr); /* print progression */ if(showprgr && rnum > 250 && i % (rnum / 250) == 0){ putchar('.'); fflush(stdout); if(i == rnum || i % (rnum / 10) == 0){ printf(" (%08d)\n", i); fflush(stdout); } } } /* close the database */ gdbm_close(dbf); if(showprgr && !err) printf("ok\n\n"); return err ? 1 : 0; } /* END OF FILE */ qdbm-1.8.78/bros/Makefile0000644000175000017500000000406610457577754014204 0ustar mikiomikio# Makefile for writing tests of DBM brothers #================================================================ # Setting variables #================================================================ # Generic settings SHELL = /bin/sh # Targets MYBINS = qdbmtest ndbmtest sdbmtest gdbmtest tdbtest cdbtest bdbtest #================================================================ # Suffix rules #================================================================ .SUFFIXES : #================================================================ # Actions #================================================================ mesg : @echo "Here are writing tests of DBM brothers." 1>&2 @echo "select a target of {all clean $(MYBINS)}." 1>&2 all : $(MYBINS) clean : rm -rf $(MYBINS) *.o *.exe a.out casket* *~ distclean : clean #================================================================ # Building binaries #================================================================ qdbmtest : qdbmtest.c gcc -I.. -I/usr/local/include -D_GNU_SOURCE=1 \ -Wall -ansi -pedantic -O3 -o $@ qdbmtest.c \ -static -L.. -L/usr/local/lib -lqdbm -lz -lc ndbmtest : ndbmtest.c gcc -I/usr/local/include -D_GNU_SOURCE=1 \ -Wall -ansi -pedantic -O3 -o $@ ndbmtest.c \ -static -L/usr/local/lib -lndbm -lc sdbmtest : sdbmtest.c gcc -I/usr/local/include -D_GNU_SOURCE=1 \ -Wall -ansi -pedantic -O3 -o $@ sdbmtest.c \ -static -L/usr/local/lib -lsdbm -lc gdbmtest : gdbmtest.c gcc -I/usr/local/include -D_GNU_SOURCE=1 \ -Wall -ansi -pedantic -O3 -o $@ gdbmtest.c \ -static -L/usr/local/lib -lgdbm -lc tdbtest : tdbtest.c gcc -I/usr/local/include -D_GNU_SOURCE=1 \ -Wall -ansi -pedantic -O3 -o $@ tdbtest.c \ -static -L/usr/local/lib -ltdb -lc cdbtest : cdbtest.c gcc -I/usr/local/include -D_GNU_SOURCE=1 \ -Wall -ansi -pedantic -O3 -o $@ cdbtest.c \ -static -L/usr/local/lib -lcdb -lc bdbtest : bdbtest.c gcc -I/usr/local/bdb/include -D_GNU_SOURCE=1 \ -Wall -O3 -o $@ bdbtest.c \ -static -L/usr/local/bdb/lib -ldb-4.4 -lpthread -lc # END OF FILE qdbm-1.8.78/bros/reporter0000755000175000017500000000705710042024142014277 0ustar mikiomikio#! /bin/sh #================================================================ # reporter # Generate a report of benchmark test #================================================================ # check arguments if [ $# != 1 ] || [ $1 -lt 1 ] then printf 'usage: reporter recnum\n' 1>&2 exit 1 fi RECNUM=$1 # function to print real time of executing a command exectime(){ sync ; sync ; sleep 1 HIDEPRGR=1 ; export HIDEPRGR TMPSTR=`( time $1 ) 2>&1 | grep real` TMPSTR=`echo $TMPSTR | sed -e 's/.* //' -e 's/s//' -e 's/m/ \* 60 + /'` perl -e "printf('%.2f', $TMPSTR);" } # function to print file size filesize(){ ls -l $1 | tr -s ' ' | tr ' ' '\t' | cut -f 5 } # print the headers printf '%s,%s,%s,%s\n' "NAME" "WRITE" "READ" "SIZE" # test of QDBM rm -rf casket* WRITETIME=`exectime "./qdbmtest write casket $RECNUM"` READTIME=`exectime "./qdbmtest read casket $RECNUM"` FILESIZE=`filesize casket` printf '%s,%s,%s,%s\n' "QDBM" "$WRITETIME" "$READTIME" "$FILESIZE" # test of NDBM rm -rf casket* WRITETIME=`exectime "./ndbmtest write casket $RECNUM"` READTIME=`exectime "./ndbmtest read casket $RECNUM"` FDIRSIZE=`filesize casket.dir` FPAGSIZE=`filesize casket.pag` FILESIZE=`expr $FDIRSIZE + $FPAGSIZE` printf '%s,%s,%s,%s\n' "NDBM" "$WRITETIME" "$READTIME" "$FILESIZE" # test of SDBM rm -rf casket* WRITETIME=`exectime "./sdbmtest write casket $RECNUM"` READTIME=`exectime "./sdbmtest read casket $RECNUM"` FDIRSIZE=`filesize casket.dir` FPAGSIZE=`filesize casket.pag` FILESIZE=`expr $FDIRSIZE + $FPAGSIZE` printf '%s,%s,%s,%s\n' "SDBM" "$WRITETIME" "$READTIME" "$FILESIZE" # test of GDBM rm -rf casket* WRITETIME=`exectime "./gdbmtest write casket $RECNUM"` READTIME=`exectime "./gdbmtest read casket $RECNUM"` FILESIZE=`filesize casket` printf '%s,%s,%s,%s\n' "GDBM" "$WRITETIME" "$READTIME" "$FILESIZE" # test of TDB rm -rf casket* WRITETIME=`exectime "./tdbtest write casket $RECNUM"` READTIME=`exectime "./tdbtest read casket $RECNUM"` FILESIZE=`filesize casket` printf '%s,%s,%s,%s\n' "TDB" "$WRITETIME" "$READTIME" "$FILESIZE" # test of CDB rm -rf casket* WRITETIME=`exectime "./cdbtest write casket $RECNUM"` READTIME=`exectime "./cdbtest read casket $RECNUM"` FILESIZE=`filesize casket` printf '%s,%s,%s,%s\n' "CDB" "$WRITETIME" "$READTIME" "$FILESIZE" # test of BDB rm -rf casket* WRITETIME=`exectime "./bdbtest write casket $RECNUM"` READTIME=`exectime "./bdbtest read casket $RECNUM"` FILESIZE=`filesize casket` printf '%s,%s,%s,%s\n' "BDB" "$WRITETIME" "$READTIME" "$FILESIZE" # test of QDBM-BT-A rm -rf casket* WRITETIME=`exectime "./qdbmtest btwrite casket $RECNUM"` READTIME=`exectime "./qdbmtest btread casket $RECNUM"` FILESIZE=`filesize casket` printf '%s,%s,%s,%s\n' "QDBM-BT-ASC" "$WRITETIME" "$READTIME" "$FILESIZE" # test of QDBM-BT-R rm -rf casket* WRITETIME=`exectime "./qdbmtest btwrite -rnd casket $RECNUM"` READTIME=`exectime "./qdbmtest btread -rnd casket $RECNUM"` FILESIZE=`filesize casket` printf '%s,%s,%s,%s\n' "QDBM-BT-RND" "$WRITETIME" "$READTIME" "$FILESIZE" # test of BDB-BT-ASC rm -rf casket* WRITETIME=`exectime "./bdbtest btwrite casket $RECNUM"` READTIME=`exectime "./bdbtest btread casket $RECNUM"` FILESIZE=`filesize casket` printf '%s,%s,%s,%s\n' "BDB-BT-ASC" "$WRITETIME" "$READTIME" "$FILESIZE" # test of BDB-BT-RND rm -rf casket* WRITETIME=`exectime "./bdbtest btwrite -rnd casket $RECNUM"` READTIME=`exectime "./bdbtest btread -rnd casket $RECNUM"` FILESIZE=`filesize casket` printf '%s,%s,%s,%s\n' "BDB-BT-RND" "$WRITETIME" "$READTIME" "$FILESIZE" # remove garbage rm -rf casket* sync ; sync # exit normally exit 0 # END OF FILE qdbm-1.8.78/bros/sdbmtest.c0000644000175000017500000001115010355663555014515 0ustar mikiomikio/************************************************************************************************* * Writing test of Substitute Database Manager *************************************************************************************************/ #include #include #include #include #include #include #undef TRUE #define TRUE 1 /* boolean true */ #undef FALSE #define FALSE 0 /* boolean false */ #define RECBUFSIZ 32 /* buffer for records */ /* global variables */ const char *progname; /* program name */ int showprgr; /* whether to show progression */ /* function prototypes */ int main(int argc, char **argv); void usage(void); int runwrite(int argc, char **argv); int runread(int argc, char **argv); int dowrite(char *name, int rnum); int doread(char *name, int rnum); /* main routine */ int main(int argc, char **argv){ int rv; progname = argv[0]; showprgr = TRUE; if(getenv("HIDEPRGR")) showprgr = FALSE; if(argc < 2) usage(); rv = 0; if(!strcmp(argv[1], "write")){ rv = runwrite(argc, argv); } else if(!strcmp(argv[1], "read")){ rv = runread(argc, argv); } else { usage(); } return rv; } /* print the usage and exit */ void usage(void){ fprintf(stderr, "%s: test cases for Substitute Database Manager\n", progname); fprintf(stderr, "\n"); fprintf(stderr, "usage:\n"); fprintf(stderr, " %s write name rnum\n", progname); fprintf(stderr, " %s read name rnum\n", progname); fprintf(stderr, "\n"); exit(1); } /* parse arguments of write command */ int runwrite(int argc, char **argv){ char *name, *rstr; int i, rnum, rv; name = NULL; rstr = NULL; rnum = 0; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ usage(); } else if(!name){ name = argv[i]; } else if(!rstr){ rstr = argv[i]; } else { usage(); } } if(!name || !rstr) usage(); rnum = atoi(rstr); if(rnum < 1) usage(); rv = dowrite(name, rnum); return rv; } /* parse arguments of read command */ int runread(int argc, char **argv){ char *name, *rstr; int i, rnum, rv; name = NULL; rstr = NULL; rnum = 0; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ usage(); } else if(!name){ name = argv[i]; } else if(!rstr){ rstr = argv[i]; } else { usage(); } } if(!name || !rstr) usage(); rnum = atoi(rstr); if(rnum < 1) usage(); rv = doread(name, rnum); return rv; } /* perform write command */ int dowrite(char *name, int rnum){ DBM *db; datum key, val; int i, err, len; char buf[RECBUFSIZ]; if(showprgr) printf("\n name=%s rnum=%d\n\n", name, rnum); /* open a database */ if(!(db = dbm_open(name, O_RDWR | O_CREAT | O_TRUNC, 00644))){ fprintf(stderr, "dbm_open failed\n"); return 1; } err = FALSE; /* loop for each record */ for(i = 1; i <= rnum; i++){ len = sprintf(buf, "%08d", i); key.dptr = buf; key.dsize = len; val.dptr = buf; val.dsize = len; /* store a record */ if(dbm_store(db, key, val, DBM_REPLACE) < 0){ fprintf(stderr, "dbm_store failed\n"); err = TRUE; break; } /* print progression */ if(showprgr && rnum > 250 && i % (rnum / 250) == 0){ putchar('.'); fflush(stdout); if(i == rnum || i % (rnum / 10) == 0){ printf(" (%08d)\n", i); fflush(stdout); } } } /* close the database */ dbm_close(db); if(showprgr && !err) printf("ok\n\n"); return err ? 1 : 0; } /* perform read command */ int doread(char *name, int rnum){ DBM *db; datum key, val; int i, err, len; char buf[RECBUFSIZ]; if(showprgr) printf("\n name=%s rnum=%d\n\n", name, rnum); /* open a database */ if(!(db = dbm_open(name, O_RDONLY, 00644))){ fprintf(stderr, "dbm_open failed\n"); return 1; } err = FALSE; /* loop for each record */ for(i = 1; i <= rnum; i++){ /* retrieve a record */ len = sprintf(buf, "%08d", i); key.dptr = buf; key.dsize = len; val = dbm_fetch(db, key); if(!val.dptr){ fprintf(stderr, "dbm_fetch failed\n"); err = TRUE; break; } /* print progression */ if(showprgr && rnum > 250 && i % (rnum / 250) == 0){ putchar('.'); fflush(stdout); if(i == rnum || i % (rnum / 10) == 0){ printf(" (%08d)\n", i); fflush(stdout); } } } /* close the database */ dbm_close(db); if(showprgr && !err) printf("ok\n\n"); return err ? 1 : 0; } /* END OF FILE */ qdbm-1.8.78/bros/result.xls0000755000175000017500000007500010523136336014566 0ustar mikiomikioÐÏࡱá>þÿ :þÿÿÿþÿÿÿ9ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ìÍÉÀá°Áâ\pmikio B°aÀ=œ¯¼=à;45,8X@"·Ú1 Üÿ€V-ÿ3ÿ 0ÿ´0·0Ã0¯01 Üÿ€V-ÿ3ÿ 0ÿ´0·0Ã0¯01 Üÿ€V-ÿ3ÿ 0ÿ´0·0Ã0¯01 Üÿ€V-ÿ3ÿ 0ÿ´0·0Ã0¯01 Üÿ€V-ÿ3ÿ 0ÿ´0·0Ã0¯01 xÿ€V-ÿ3ÿ 0ÿ´0·0Ã0¯01  ÿ€V-ÿ3ÿ 0ÿ´0·0Ã0¯01  ÿ€V-ÿ3ÿ 0ÿ´0·0Ã0¯01  ÿ€V-ÿ3ÿ 0ÿ´0·0Ã0¯01  ÿ€V-ÿ3ÿ 0ÿ´0·0Ã0¯01 –ÿ€V-ÿ3ÿ 0ÿ´0·0Ã0¯01 ªÿ€V-ÿ3ÿ 0ÿ´0·0Ã0¯01  ÿ€V-ÿ3ÿ 0ÿ´0·0Ã0¯01ÿ¼VCentury1ÈÿVCentury1Üÿ¼VCentury1 ÿVCentury1´ÿVCentury1 Œÿ€V-ÿ3ÿ 0ÿ´0·0Ã0¯0"\"#,##0;"\"\-#,##0"\"#,##0;[Red]"\"\-#,##0"\"#,##0.00;"\"\-#,##0.00#"\"#,##0.00;[Red]"\"\-#,##0.007*2_ "\"* #,##0_ ;_ "\"* \-#,##0_ ;_ "\"* "-"_ ;_ @_ .))_ * #,##0_ ;_ * \-#,##0_ ;_ * "-"_ ;_ @_ ?,:_ "\"* #,##0.00_ ;_ "\"* \-#,##0.00_ ;_ "\"* "-"??_ ;_ @_ 6+1_ * #,##0.00_ ;_ * \-#,##0.00_ ;_ * "-"??_ ;_ @_ \$#,##0_);\(\$#,##0\)\$#,##0_);[Red]\(\$#,##0\) \$#,##0.00_);\(\$#,##0.00\)% \$#,##0.00_);[Red]\(\$#,##0.00\) °0.00_ ±0_ àõÿ À àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ à À à õÿ øÀ à&õÿ øÀ à(õÿ øÀ àõÿ øÀ àõÿ øÀ à1À à1À à1À à1|@ @ 7 à1À à1|@ @  à1|@ @  à°<@ @ À à±<@ @ À àÀ à1<À “€ÿ“€ÿ“€ÿ“€ÿ“€ÿ“€ÿ`… qsheetŒQQ®  ;:ÁÁ`iëZðRð3 ð¿ À@@ñ  ÷üo!!Benchmark Test of DBM BrothersResultNAMEQDBMNDBMSDBMGDBMTDBCDBBDB QDBM-BT-ASC QDBM-BT-RND BDB-BT-ASC BDB-BT-RND DESCRIPTION 5!Substitute Database Manager 1.0.2 5GNU Database Manager 1.8.3 5%B+ tree API of QDBM (ascending order) 5B+ tree API of QDBM (at random) 5 WRITE TIME 5 READ TIME 5Graph of Processing Time 5$B+ tree API of BDB (ascending order) 5B+ tree API of BDB (at random) 5Graph of File Size 5›Unit of time is seconds. Unit of size is kilo bytes. Read time of SDBM can not be calculated because its database is broken when more than 100000 records. 5 FILE SIZE 5New Database Manager 5.1 5Trivial Database 1.0.6 5Tiny Constant Database 0.75 5Berkeley DB 4.4.20 5øThis benchmark test is to calculate processing time (real time) and file size of database. Writing test is to store 1,000,000 records. Reading test is to fetch all of its records. Both of the key and the value of each record are such 8-byte strings as `00000001', `00000002', `00000003'... Tuning parameters of each DBM are set to display its best performance. Platform: Linux 2.4.31 kernel, EXT2 file system, Pentium4 1.7GHz CPU, 1024MB RAM, ThinkPad T42 Compilation: gcc 3.3.2 (using -O3), glibc 2.3.3 5Quick Database Manager 1.8.74 5ÿ*¿  _® û1 ~ò?ccj ìÍÉÀ +sãc  dü©ñÒMbP?_*+‚€%ÿÁƒ„&×£p= ×ã?'Âõ(\â?(º\.—Ëåâ?)º\.—Ëåâ?MDocuWorks PrinterDriverÜ0. š 4dXXDW30....ô¡" dXX ƒÁ`à? ƒÁ`à?U} €} @}  } À }  +K@•@ð@&@´@;@x@ÀÀ À À À À ÀÀÀÀÀÀ@Ò@Y@x@ý ý ¾ý ý ý ý ý ý ý ý  ½ g@Àc@ ûê@ý ý ½ 8‰@Xˆ@æµ1ý ý ½ °‘@„"Aý ý ½ ä•@À€@@6ô@ý ý ½  Ž@Àk@îè@ý ý ½ ÀU@T@ã@ý  ý ½Ž@@€ÿã@ý  ý ½ m@@f@@è»×@ý  ý ½‘@ ~@àÎ@ý  ý ½s@ s@àÚ@ý  ý ½X@ðy@pÜ@ý ¾ý ×2¸ FD888888DD88 (Ò@)Y@*x@ý )× J(ìÈð8ðð ð( ð ððp’ ð “ ð6¿NƒM¿ÀMÿ?¿ð(ð]`í  ìÍÉÀƒ„M¢Acrobat DistillerÜÄo š 4dXXA4PRIVB''''ÄP4(ˆ † ÿÿ¡" dXXü©ñÒMbà?ü©ñÒMbà?3` ‚#Ü` ‚#Ü` 1&¥ŒèèÙ3 dö²23 ÿÿ M ÿÿÿNM4  3Q1:  WRITE TIMEQ° ;Q1 ;Qÿÿ3_ O €€€ÿÿÿ  MM<4E4  3Q1:  READ TIMEQ° ;Q1 ;Qÿÿ3_ O ÀÀÀÿÿÿ  MM<4E4D$% âÿÿÿ¹ÿÿÿ±MP(3O&Q4$% âÿÿÿ¹ÿÿÿ±MP(3O&Q4FAñ­3 e 3O;[¶3 bï&43*.@ð?ð?N±! ÿÿ M4523 €€€ ÿÿÿNM43–"  Ê ô3O ÆE% âÿÿÿ¹ÿÿÿ±M *3O& Q423 ÿÿ M ÿÿÿNM44444 eee ìxðp’ ð “ ð6¿NƒM¿ÀMÿ?¿ð+;ð]`ôí  ìÍÉÀƒ„M¢Acrobat DistillerÜÄo š 4dXXA4PRIVB''''ÄP4(ˆ † ÿÿ¡" dXXü©ñÒMbà?ü©ñÒMbà?3` ‚#Ü ` ‚#Ü ` Æ&=Œ ` '=  èÀÌ3 d 23 ÿÿ M ÿÿÿNM4  3Q1:  FILE SIZEQ± ;Q1 ;Qÿÿ3_ O –––ÿÿÿ7  MM<4E4D$% âÿÿÿ´ÿÿÿ±MP(3O& Q4$% âÿÿÿ´ÿÿÿ±MP(3O& Q4FApý ˜ 3O;üC 3 bï& 43*jø@& ! ÿÿ M4523 €€€ ÿÿÿNM43–" 44% âÿÿÿ´ÿÿÿñMP3OQ'44 eee >¶@Kdåï5 ìÍáÁ¿Àâ\pmikio [B¤bœsheet$ ;ÿÿ:=à;45,8X@"·Ú1Üÿ€V‚l‚r ‚oƒSƒVƒbƒN1Üÿ€V‚l‚r ‚oƒSƒVƒbƒN1Üÿ€V‚l‚r ‚oƒSƒVƒbƒN1Üÿ€V‚l‚r ‚oƒSƒVƒbƒN1Üÿ€V‚l‚r ‚oƒSƒVƒbƒN1xÿ€V‚l‚r ‚oƒSƒVƒbƒN1 ÿ€V‚l‚r ‚oƒSƒVƒbƒN1 ÿ€V‚l‚r ‚oƒSƒVƒbƒN1 ÿ€V‚l‚r ‚oƒSƒVƒbƒN1 ÿ€V‚l‚r ‚oƒSƒVƒbƒN1–ÿ€V‚l‚r ‚oƒSƒVƒbƒN1ªÿ€V‚l‚r ‚oƒSƒVƒbƒN1 ÿ€V‚l‚r ‚oƒSƒVƒbƒN1ÿ¼VCentury1ÈÿVCentury1Üÿ¼VCentury1 ÿVCentury1´ÿVCentury1Œÿ€V‚l‚r ‚oƒSƒVƒbƒN"\"#,##0;"\"\-#,##0"\"#,##0;[Red]"\"\-#,##0"\"#,##0.00;"\"\-#,##0.00!"\"#,##0.00;[Red]"\"\-#,##0.005*2_ "\"* #,##0_ ;_ "\"* \-#,##0_ ;_ "\"* "-"_ ;_ @_ ,))_ * #,##0_ ;_ * \-#,##0_ ;_ * "-"_ ;_ @_ =,:_ "\"* #,##0.00_ ;_ "\"* \-#,##0.00_ ;_ "\"* "-"??_ ;_ @_ 4+1_ * #,##0.00_ ;_ * \-#,##0.00_ ;_ * "-"??_ ;_ @_ \$#,##0_);\(\$#,##0\)\$#,##0_);[Red]\(\$#,##0\)\$#,##0.00_);\(\$#,##0.00\)# \$#,##0.00_);[Red]\(\$#,##0.00\) °0.00_ ±0_ àõÿ À àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ à À à õÿ øÀ à&õÿ øÀ à(õÿ øÀ àõÿ øÀ àõÿ øÀ à1À à1À à1À à1|7 A€I€@ à1À à1| A€I€@ à1| A€I€@ à°<À @€I€@ à±<À @€I€@ àÀ à1<À “€ÿ“€ÿ“€ÿ“€ÿ“€ÿ“€ÿ’â8ÿÿÿÿÿÿÿÿÿÿÿÿ€€€€€€€€€ÀÀÀ€€€™™ÿ™3fÿÿÌÌÿÿffÿ€€fÌÌÌÿ€ÿÿÿÿÿÿ€€€€€ÿÌÿÌÿÿÌÿÌÿÿ™™Ìÿÿ™ÌÌ™ÿããã3fÿ3ÌÌ™ÌÿÌÿ™ÿfff™–––3f3™f333™3™3f33™333… 9 sheet ìÍ + ¬<  dü©ñÒMbP?_*+‚€%ÿŒQQÁƒ„&×£p= ×ã?'Âõ(\â?(º\.—Ëåâ?)º\.—Ëåâ?MÎDocuWorks Printerœ0. š 4dXX‰`‰ 0{ê0Ô‰؉ì‰6¯ 0DW30....ô¡" dXX ƒÁ`à? ƒÁ`à?U} €} @}  } À }   +K@•@ð@&@´@;@x@ÀÀ À À À À ÀÀÀÀÀÀ@Ò@Y@x@&Benchmark Test of DBM BrothersÿThis benchmark test is to calculate processing time (real time) and file size of database. Writing test is to store 1,000,000 records. Reading test is to fetch all of its records. Both of the key and the value of each record are such 8-byte strings as `0¾Result NAME DESCRIPTION WRITE TIME READ TIME FILE SIZE QDBM%Quick Database Manager 1.8.74½ g@Àc@ ûê@ NDBM New Database Manager 5.1½ 8‰@Xˆ@æµ1 SDBM) !Substitute Database Manager 1.0.2½ °‘@„"A GDBM" GNU Database Manager 1.8.3½ ä•@À€@@6ô@ TDB Trivial Database 1.0.6½  Ž@Àk@îè@ CDB# Tiny Constant Database 0.75½ ÀU@T@ã@ BDBBerkeley DB 4.4.20½Ž@@€ÿã@ QDBM-BT-ASC-%B+ tree API of QDBM (ascending order)½ m@@f@@è»×@ QDBM-BT-RND'B+ tree API of QDBM (at random)½‘@ ~@àÎ@ BDB-BT-ASC,$B+ tree API of BDB (ascending order)½s@ s@àÚ@ BDB-BT-RND&B+ tree API of BDB (at random)½X@ðy@pÜ@£›Unit of time is seconds. Unit of size is kilo bytes. Read time of SDBM can not be calculated because its database is broken when more than 100000 records.¾ Graph of Processing Time×2E¸*gaPYRMRIpjb\¹$(Ò@)Y@*x@)Graph of File Size× Z(]>(@A@Ì<2üÚH)2  ì̓„MbAcrobat Distiller(œÄo š 4dXXA4 of SDBM can not be calculatePRIVB''''ÄP4(ˆ † ÿÿ¡" dXXü©ñÒMbà?ü©ñÒMbà?3èèÙ3 23 ÿÿ  ÿÿÿ4  3Q1:ÿÿ  WRITE TIMEQ°;ÿÿQ1;ÿÿÿÿ3   €€€ÿÿÿ   4E4  3Q1:ÿÿ  READ TIMEQ°;ÿÿQ1;ÿÿÿÿ3   ÀÀÀÿÿÿ   4E4D FAñ­3 e 3O;[¶3 &43*.@ð?ð?N±! ÿÿ 4523 €€€  ÿÿÿ43–"  Ê ô3O ÆE%âÿÿÿ¹ÿÿÿ±3O& Q423 ÿÿ  ÿÿÿ44$%âÿÿÿ¹ÿÿÿ±3O&Q4444  ]>+;@A@¬C2pÚH)2  ì̓„MbAcrobat Distiller;œÄo š 4dXXA4 of SDBM can not be calculatePRIVB''''ÄP4(ˆ † ÿÿ¡" dXXü©ñÒMbà?ü©ñÒMbà?3èÀÌ3 23 ÿÿ  ÿÿÿ4  3Q1:ÿÿ  FILE SIZEQ±;ÿÿQ1;ÿÿÿÿ3   –––ÿÿÿ   4E4D FApý ˜ 3O;üC 3 & 43*jø@& ! ÿÿ 4523 €€€  ÿÿÿ43–" $%âÿÿÿ´ÿÿÿ±3O& Q444%âÿÿÿ´ÿÿÿñ3OQ'44  =à;45,8X> ¶«" Àÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ þÿà…ŸòùOh«‘+'³Ù0ð PX€œ¬ Ä Ð Üè¤ Benchmark Test of DBM BrothersMikio HirabayashimikioMicrosoft Excel@=øKK¶Æ@‹¬h"Ä@€0tÈ+ÇþÿÕÍÕœ.“—+,ù®0È8@ LT \ ƒ¤ sheetsheet!Print_Area  ƒ[ƒNƒV[ƒg –¼‘O•t‚«ˆê—— þÿÿÿ !"#$%&'(þÿÿÿ*+,-./0þÿÿÿ2345678þÿÿÿýÿÿÿ;þÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿRoot EntryÿÿÿÿÿÿÿÿÀFþÿÿÿBook ÿÿÿÿÿÿÿÿÿÿÿÿL$Workbookÿÿÿÿÿÿÿÿ½+SummaryInformation(ÿÿÿÿ)DocumentSummaryInformation8ÿÿÿÿÿÿÿÿÿÿÿÿ1ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿqdbm-1.8.78/bros/qdbmtest.c0000644000175000017500000002137010457613250014506 0ustar mikiomikio/************************************************************************************************* * Writing test of Quick Database Manager *************************************************************************************************/ #include #include #include #include #include #include #undef TRUE #define TRUE 1 /* boolean true */ #undef FALSE #define FALSE 0 /* boolean false */ #define RECBUFSIZ 32 /* buffer for records */ /* global variables */ const char *progname; /* program name */ int showprgr; /* whether to show progression */ /* function prototypes */ int main(int argc, char **argv); void usage(void); int runwrite(int argc, char **argv); int runread(int argc, char **argv); int runbtwrite(int argc, char **argv); int runbtread(int argc, char **argv); int myrand(void); int dowrite(char *name, int rnum); int doread(char *name, int rnum); int dobtwrite(char *name, int rnum, int rnd); int dobtread(char *name, int rnum, int rnd); /* main routine */ int main(int argc, char **argv){ int rv; progname = argv[0]; showprgr = TRUE; if(getenv("HIDEPRGR")) showprgr = FALSE; srand48(1978); if(argc < 2) usage(); rv = 0; if(!strcmp(argv[1], "write")){ rv = runwrite(argc, argv); } else if(!strcmp(argv[1], "read")){ rv = runread(argc, argv); } else if(!strcmp(argv[1], "btwrite")){ rv = runbtwrite(argc, argv); } else if(!strcmp(argv[1], "btread")){ rv = runbtread(argc, argv); } else { usage(); } return rv; } /* print the usage and exit */ void usage(void){ fprintf(stderr, "%s: test cases for Quick Database Manager\n", progname); fprintf(stderr, "\n"); fprintf(stderr, "usage:\n"); fprintf(stderr, " %s write name rnum\n", progname); fprintf(stderr, " %s read name rnum\n", progname); fprintf(stderr, " %s btwrite [-rnd] name rnum\n", progname); fprintf(stderr, " %s btread [-rnd] name rnum\n", progname); fprintf(stderr, "\n"); exit(1); } /* parse arguments of write command */ int runwrite(int argc, char **argv){ char *name, *rstr; int i, rnum, rv; name = NULL; rstr = NULL; rnum = 0; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ usage(); } else if(!name){ name = argv[i]; } else if(!rstr){ rstr = argv[i]; } else { usage(); } } if(!name || !rstr) usage(); rnum = atoi(rstr); if(rnum < 1) usage(); rv = dowrite(name, rnum); return rv; } /* parse arguments of read command */ int runread(int argc, char **argv){ char *name, *rstr; int i, rnum, rv; name = NULL; rstr = NULL; rnum = 0; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ usage(); } else if(!name){ name = argv[i]; } else if(!rstr){ rstr = argv[i]; } else { usage(); } } if(!name || !rstr) usage(); rnum = atoi(rstr); if(rnum < 1) usage(); rv = doread(name, rnum); return rv; } /* parse arguments of btwrite command */ int runbtwrite(int argc, char **argv){ char *name, *rstr; int i, rnum, rnd, rv; name = NULL; rstr = NULL; rnum = 0; rnd = FALSE; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ if(!name && !strcmp(argv[i], "-rnd")){ rnd = TRUE; } else { usage(); } } else if(!name){ name = argv[i]; } else if(!rstr){ rstr = argv[i]; } else { usage(); } } if(!name || !rstr) usage(); rnum = atoi(rstr); if(rnum < 1) usage(); rv = dobtwrite(name, rnum, rnd); return rv; } /* parse arguments of btread command */ int runbtread(int argc, char **argv){ char *name, *rstr; int i, rnum, rnd, rv; name = NULL; rstr = NULL; rnum = 0; rnd = FALSE; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ if(!name && !strcmp(argv[i], "-rnd")){ rnd = TRUE; } else { usage(); } } else if(!name){ name = argv[i]; } else if(!rstr){ rstr = argv[i]; } else { usage(); } } if(!name || !rstr) usage(); rnum = atoi(rstr); if(rnum < 1) usage(); rv = dobtread(name, rnum, rnd); return rv; } /* pseudo random number generator */ int myrand(void){ static int cnt = 0; return (lrand48() + cnt++) & 0x7FFFFFFF; } /* perform write command */ int dowrite(char *name, int rnum){ DEPOT *depot; int i, err, len; char buf[RECBUFSIZ]; if(showprgr) printf("\n name=%s rnum=%d\n\n", name, rnum); /* open a database */ if(!(depot = dpopen(name, DP_OWRITER | DP_OCREAT | DP_OTRUNC, rnum * 3))){ fprintf(stderr, "dpopen failed\n"); return 1; } err = FALSE; /* loop for each record */ for(i = 1; i <= rnum; i++){ /* store a record */ len = sprintf(buf, "%08d", i); if(!dpput(depot, buf, len, buf, len, DP_DOVER)){ fprintf(stderr, "dpput failed\n"); err = TRUE; break; } /* print progression */ if(showprgr && rnum > 250 && i % (rnum / 250) == 0){ putchar('.'); fflush(stdout); if(i == rnum || i % (rnum / 10) == 0){ printf(" (%08d)\n", i); fflush(stdout); } } } /* close the database */ if(!dpclose(depot)){ fprintf(stderr, "dpclose failed\n"); return 1; } if(showprgr && !err) printf("ok\n\n"); return err ? 1 : 0; } /* perform read command */ int doread(char *name, int rnum){ DEPOT *depot; int i, err, len; char buf[RECBUFSIZ], vbuf[RECBUFSIZ]; if(showprgr) printf("\n name=%s rnum=%d\n\n", name, rnum); /* open a database */ if(!(depot = dpopen(name, DP_OREADER, -1))){ fprintf(stderr, "dpopen failed\n"); return 1; } err = FALSE; /* loop for each record */ for(i = 1; i <= rnum; i++){ /* store a record */ len = sprintf(buf, "%08d", i); if(dpgetwb(depot, buf, len, 0, RECBUFSIZ, vbuf) == -1){ fprintf(stderr, "dpget failed\n"); err = TRUE; break; } /* print progression */ if(showprgr && rnum > 250 && i % (rnum / 250) == 0){ putchar('.'); fflush(stdout); if(i == rnum || i % (rnum / 10) == 0){ printf(" (%08d)\n", i); fflush(stdout); } } } /* close the database */ if(!dpclose(depot)){ fprintf(stderr, "dpclose failed\n"); return 1; } if(showprgr && !err) printf("ok\n\n"); return err ? 1 : 0; } /* perform btwrite command */ int dobtwrite(char *name, int rnum, int rnd){ VILLA *villa; int i, err, len; char buf[RECBUFSIZ]; if(showprgr) printf("\n name=%s rnum=%d\n\n", name, rnum); /* open a database */ if(!(villa = vlopen(name, VL_OWRITER | VL_OCREAT | VL_OTRUNC, VL_CMPLEX))){ fprintf(stderr, "vlopen failed\n"); return 1; } if(rnd){ vlsettuning(villa, 77, 256, rnum / 77, -1); } else { vlsettuning(villa, 101, 256, 16, 16); } err = FALSE; /* loop for each record */ for(i = 1; i <= rnum; i++){ /* store a record */ len = sprintf(buf, "%08d", rnd ? myrand() % rnum + 1 : i); if(!vlput(villa, buf, len, buf, len, VL_DOVER)){ fprintf(stderr, "vlput failed\n"); err = TRUE; break; } /* print progression */ if(showprgr && rnum > 250 && i % (rnum / 250) == 0){ putchar('.'); fflush(stdout); if(i == rnum || i % (rnum / 10) == 0){ printf(" (%08d)\n", i); fflush(stdout); } } } /* close the database */ if(!vlclose(villa)){ fprintf(stderr, "vlclose failed\n"); return 1; } if(showprgr && !err) printf("ok\n\n"); return err ? 1 : 0; } /* perform btread command */ int dobtread(char *name, int rnum, int rnd){ VILLA *villa; int i, err, len; const char *val; char buf[RECBUFSIZ]; if(showprgr) printf("\n name=%s rnum=%d\n\n", name, rnum); /* open a database */ if(!(villa = vlopen(name, VL_OREADER, VL_CMPLEX))){ fprintf(stderr, "vlopen failed\n"); return 1; } if(rnd){ vlsettuning(villa, 37, 200, rnum / 45, 512); } else { vlsettuning(villa, 101, 256, 16, 16); } err = FALSE; /* loop for each record */ for(i = 1; i <= rnum; i++){ /* store a record */ len = sprintf(buf, "%08d", rnd ? myrand() % rnum + 1 : i); if(!(val = vlgetcache(villa, buf, len, NULL))){ fprintf(stderr, "vlget failed\n"); err = TRUE; break; } /* print progression */ if(showprgr && rnum > 250 && i % (rnum / 250) == 0){ putchar('.'); fflush(stdout); if(i == rnum || i % (rnum / 10) == 0){ printf(" (%08d)\n", i); fflush(stdout); } } } /* close the database */ if(!vlclose(villa)){ fprintf(stderr, "vlclose failed\n"); return 1; } if(showprgr && !err) printf("ok\n\n"); return err ? 1 : 0; } /* END OF FILE */ qdbm-1.8.78/bros/ndbmtest.c0000644000175000017500000001116610355663555014517 0ustar mikiomikio/************************************************************************************************* * Writing test of New Database Manager *************************************************************************************************/ #include #include #include #include #include #include #undef TRUE #define TRUE 1 /* boolean true */ #undef FALSE #define FALSE 0 /* boolean false */ #define RECBUFSIZ 32 /* buffer for records */ /* global variables */ const char *progname; /* program name */ int showprgr; /* whether to show progression */ /* function prototypes */ int main(int argc, char **argv); void usage(void); int runwrite(int argc, char **argv); int runread(int argc, char **argv); int dowrite(char *name, int rnum); int doread(char *name, int rnum); /* main routine */ int main(int argc, char **argv){ int rv; progname = argv[0]; showprgr = TRUE; if(getenv("HIDEPRGR")) showprgr = FALSE; if(argc < 2) usage(); rv = 0; if(!strcmp(argv[1], "write")){ rv = runwrite(argc, argv); } else if(!strcmp(argv[1], "read")){ rv = runread(argc, argv); } else { usage(); } return rv; } /* print the usage and exit */ void usage(void){ fprintf(stderr, "%s: test cases for New Database Manager\n", progname); fprintf(stderr, "\n"); fprintf(stderr, "usage:\n"); fprintf(stderr, " %s write name rnum\n", progname); fprintf(stderr, " %s read name rnum\n", progname); fprintf(stderr, "\n"); exit(1); } /* parse arguments of write command */ int runwrite(int argc, char **argv){ char *name, *rstr; int i, rnum, rv; name = NULL; rstr = NULL; rnum = 0; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ usage(); } else if(!name){ name = argv[i]; } else if(!rstr){ rstr = argv[i]; } else { usage(); } } if(!name || !rstr) usage(); rnum = atoi(rstr); if(rnum < 1) usage(); rv = dowrite(name, rnum); return rv; } /* parse arguments of read command */ int runread(int argc, char **argv){ char *name, *rstr; int i, rnum, rv; name = NULL; rstr = NULL; rnum = 0; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ usage(); } else if(!name){ name = argv[i]; } else if(!rstr){ rstr = argv[i]; } else { usage(); } } if(!name || !rstr) usage(); rnum = atoi(rstr); if(rnum < 1) usage(); rv = doread(name, rnum); return rv; } /* perform write command */ int dowrite(char *name, int rnum){ DBM *db; datum key, content; int i, err, len; char buf[RECBUFSIZ]; if(showprgr) printf("\n name=%s rnum=%d\n\n", name, rnum); /* open a database */ if(!(db = dbm_open(name, O_RDWR | O_CREAT | O_TRUNC, 00644))){ fprintf(stderr, "dbm_open failed\n"); return 1; } err = FALSE; /* loop for each record */ for(i = 1; i <= rnum; i++){ len = sprintf(buf, "%08d", i); key.dptr = buf; key.dsize = len; content.dptr = buf; content.dsize = len; /* store a record */ if(dbm_store(db, key, content, DBM_REPLACE) < 0){ fprintf(stderr, "dbm_store failed\n"); err = TRUE; break; } /* print progression */ if(showprgr && rnum > 250 && i % (rnum / 250) == 0){ putchar('.'); fflush(stdout); if(i == rnum || i % (rnum / 10) == 0){ printf(" (%08d)\n", i); fflush(stdout); } } } /* close the database */ dbm_close(db); if(showprgr && !err) printf("ok\n\n"); return err ? 1 : 0; } /* perform read command */ int doread(char *name, int rnum){ DBM *db; datum key, content; int i, err, len; char buf[RECBUFSIZ]; if(showprgr) printf("\n name=%s rnum=%d\n\n", name, rnum); /* open a database */ if(!(db = dbm_open(name, O_RDONLY, 00644))){ fprintf(stderr, "dbm_open failed\n"); return 1; } err = FALSE; /* loop for each record */ for(i = 1; i <= rnum; i++){ /* retrieve a record */ len = sprintf(buf, "%08d", i); key.dptr = buf; key.dsize = len; content = dbm_fetch(db, key); if(!content.dptr){ fprintf(stderr, "dbm_fetch failed\n"); err = TRUE; break; } /* print progression */ if(showprgr && rnum > 250 && i % (rnum / 250) == 0){ putchar('.'); fflush(stdout); if(i == rnum || i % (rnum / 10) == 0){ printf(" (%08d)\n", i); fflush(stdout); } } } /* close the database */ dbm_close(db); if(showprgr && !err) printf("ok\n\n"); return err ? 1 : 0; } /* END OF FILE */ qdbm-1.8.78/bros/cdbtest.c0000644000175000017500000001134510457573327014326 0ustar mikiomikio#include #include #include #include #include #include #include #include #include "cdb.h" #undef TRUE #define TRUE 1 /* boolean true */ #undef FALSE #define FALSE 0 /* boolean false */ #define RECBUFSIZ 32 /* buffer for records */ /* global variables */ const char *progname; /* program name */ int showprgr; /* whether to show progression */ /* function prototypes */ int main(int argc, char **argv); void usage(void); int runwrite(int argc, char **argv); int runread(int argc, char **argv); int dowrite(char *name, int rnum); int doread(char *name, int rnum); /* main routine */ int main(int argc, char **argv){ int rv; progname = argv[0]; showprgr = TRUE; if(getenv("HIDEPRGR")) showprgr = FALSE; if(argc < 2) usage(); rv = 0; if(!strcmp(argv[1], "write")){ rv = runwrite(argc, argv); } else if(!strcmp(argv[1], "read")){ rv = runread(argc, argv); } else { usage(); } return rv; } /* print the usage and exit */ void usage(void){ fprintf(stderr, "%s: test cases for GNU Database Manager\n", progname); fprintf(stderr, "\n"); fprintf(stderr, "usage:\n"); fprintf(stderr, " %s write name rnum\n", progname); fprintf(stderr, " %s read name rnum\n", progname); fprintf(stderr, "\n"); exit(1); } /* parse arguments of write command */ int runwrite(int argc, char **argv){ char *name, *rstr; int i, rnum, rv; name = NULL; rstr = NULL; rnum = 0; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ usage(); } else if(!name){ name = argv[i]; } else if(!rstr){ rstr = argv[i]; } else { usage(); } } if(!name || !rstr) usage(); rnum = atoi(rstr); if(rnum < 1) usage(); rv = dowrite(name, rnum); return rv; } /* parse arguments of read command */ int runread(int argc, char **argv){ char *name, *rstr; int i, rnum, rv; name = NULL; rstr = NULL; rnum = 0; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ usage(); } else if(!name){ name = argv[i]; } else if(!rstr){ rstr = argv[i]; } else { usage(); } } if(!name || !rstr) usage(); rnum = atoi(rstr); if(rnum < 1) usage(); rv = doread(name, rnum); return rv; } /* perform write command */ int dowrite(char *name, int rnum){ struct cdb_make cdb; int i, fd, err, len; char buf[32]; if(showprgr) printf("\n name=%s rnum=%d\n\n", name, rnum); /* open a database */ if((fd = open("casket", O_RDWR | O_CREAT | O_TRUNC, 0644)) == -1){ perror("open"); return 1; } if(cdb_make_start(&cdb, fd) == -1){ perror("cdb_make_start"); close(fd); return 1; } err = FALSE; /* loop for each record */ for(i = 1; i <= rnum; i++){ /* store a record */ len = sprintf(buf, "%08d", i); if(cdb_make_add(&cdb, buf, len, buf, len) == -1){ perror("cdb_add"); err = TRUE; break; } /* print progression */ if(showprgr && rnum > 250 && i % (rnum / 250) == 0){ putchar('.'); fflush(stdout); if(i == rnum || i % (rnum / 10) == 0){ printf(" (%08d)\n", i); fflush(stdout); } } } /* close the database */ if(cdb_make_finish(&cdb) == -1){ perror("cdb_make_finish"); close(fd); return 1; } if(close(fd) == -1){ perror("close"); return 1; } if(showprgr && !err) printf("ok\n\n"); return err ? 1 : 0; } /* perform read command */ int doread(char *name, int rnum){ struct cdb cdb; int i, fd, err, len; char buf[RECBUFSIZ], *val; if(showprgr) printf("\n name=%s rnum=%d\n\n", name, rnum); /* open a database */ if((fd = open("casket", O_RDONLY, 0644)) == -1){ perror("open"); return 1; } cdb_init(&cdb, fd); err = FALSE; /* loop for each record */ for(i = 1; i <= rnum; i++){ /* retrieve a record */ len = sprintf(buf, "%08d", i); if(cdb_find(&cdb, buf, len) == 0){ perror("cdb_find"); err = TRUE; break; } len = cdb_datalen(&cdb); if(!(val = malloc(len + 1))){ perror("malloc"); err = TRUE; break; } cdb_read(&cdb, val, len, cdb_datapos(&cdb)); free(val); /* print progression */ if(showprgr && rnum > 250 && i % (rnum / 250) == 0){ putchar('.'); fflush(stdout); if(i == rnum || i % (rnum / 10) == 0){ printf(" (%08d)\n", i); fflush(stdout); } } } /* close the database */ cdb_free(&cdb); if(close(fd) == -1){ perror("close"); return 1; } if(showprgr && !err) printf("ok\n\n"); return err ? 1 : 0; } /* END OF FILE */ qdbm-1.8.78/bros/tdbtest.c0000644000175000017500000001126610355663555014351 0ustar mikiomikio/************************************************************************************************* * Writing test of Trivial Database *************************************************************************************************/ #include #include #include #include #include #include #undef TRUE #define TRUE 1 /* boolean true */ #undef FALSE #define FALSE 0 /* boolean false */ #define RECBUFSIZ 32 /* buffer for records */ /* global variables */ const char *progname; /* program name */ int showprgr; /* whether to show progression */ /* function prototypes */ int main(int argc, char **argv); void usage(void); int runwrite(int argc, char **argv); int runread(int argc, char **argv); int dowrite(char *name, int rnum); int doread(char *name, int rnum); /* main routine */ int main(int argc, char **argv){ int rv; progname = argv[0]; showprgr = TRUE; if(getenv("HIDEPRGR")) showprgr = FALSE; if(argc < 2) usage(); rv = 0; if(!strcmp(argv[1], "write")){ rv = runwrite(argc, argv); } else if(!strcmp(argv[1], "read")){ rv = runread(argc, argv); } else { usage(); } return rv; } /* print the usage and exit */ void usage(void){ fprintf(stderr, "%s: test cases for Trivial Database\n", progname); fprintf(stderr, "\n"); fprintf(stderr, "usage:\n"); fprintf(stderr, " %s write name rnum\n", progname); fprintf(stderr, " %s read name rnum\n", progname); fprintf(stderr, "\n"); exit(1); } /* parse arguments of write command */ int runwrite(int argc, char **argv){ char *name, *rstr; int i, rnum, rv; name = NULL; rstr = NULL; rnum = 0; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ usage(); } else if(!name){ name = argv[i]; } else if(!rstr){ rstr = argv[i]; } else { usage(); } } if(!name || !rstr) usage(); rnum = atoi(rstr); if(rnum < 1) usage(); rv = dowrite(name, rnum); return rv; } /* parse arguments of read command */ int runread(int argc, char **argv){ char *name, *rstr; int i, rnum, rv; name = NULL; rstr = NULL; rnum = 0; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ usage(); } else if(!name){ name = argv[i]; } else if(!rstr){ rstr = argv[i]; } else { usage(); } } if(!name || !rstr) usage(); rnum = atoi(rstr); if(rnum < 1) usage(); rv = doread(name, rnum); return rv; } /* perform write command */ int dowrite(char *name, int rnum){ TDB_CONTEXT *tdb; TDB_DATA key, record; int i, err, len; char buf[RECBUFSIZ]; if(showprgr) printf("\n name=%s rnum=%d\n\n", name, rnum); /* open a database */ if(!(tdb = tdb_open(name, rnum * 2, 0, O_RDWR | O_CREAT | O_TRUNC, 00644))){ fprintf(stderr, "tdb_open failed\n"); return 1; } err = FALSE; /* loop for each record */ for(i = 1; i <= rnum; i++){ len = sprintf(buf, "%08d", i); key.dptr = buf; key.dsize = len; record.dptr = buf; record.dsize = len; /* store a record */ if(tdb_store(tdb, key, record, TDB_REPLACE) != 0){ fprintf(stderr, "tdb_store failed\n"); err = TRUE; break; } /* print progression */ if(showprgr && rnum > 250 && i % (rnum / 250) == 0){ putchar('.'); fflush(stdout); if(i == rnum || i % (rnum / 10) == 0){ printf(" (%08d)\n", i); fflush(stdout); } } } /* close the database */ tdb_close(tdb); if(showprgr && !err) printf("ok\n\n"); return err ? 1 : 0; } /* perform read command */ int doread(char *name, int rnum){ TDB_CONTEXT *tdb; TDB_DATA key, record; int i, err, len; char buf[RECBUFSIZ]; if(showprgr) printf("\n name=%s rnum=%d\n\n", name, rnum); /* open a database */ if(!(tdb = tdb_open(name, rnum * 2, 0, O_RDONLY, 00644))){ fprintf(stderr, "tdb_open failed\n"); return 1; } err = FALSE; /* loop for each record */ for(i = 1; i <= rnum; i++){ len = sprintf(buf, "%08d", i); key.dptr = buf; key.dsize = len; /* retrieve a record */ record = tdb_fetch(tdb, key); if(!record.dptr){ fprintf(stderr, "tdb_fetch failed\n"); err = TRUE; break; } free(record.dptr); /* print progression */ if(showprgr && rnum > 250 && i % (rnum / 250) == 0){ putchar('.'); fflush(stdout); if(i == rnum || i % (rnum / 10) == 0){ printf(" (%08d)\n", i); fflush(stdout); } } } /* close the database */ tdb_close(tdb); if(showprgr && !err) printf("ok\n\n"); return err ? 1 : 0; } /* END OF FILE */ qdbm-1.8.78/bros/bdbtest.c0000644000175000017500000002532310457600136014313 0ustar mikiomikio/************************************************************************************************* * Writing test of Berkeley DB *************************************************************************************************/ #include #include #include #include #undef TRUE #define TRUE 1 /* boolean true */ #undef FALSE #define FALSE 0 /* boolean false */ #define RECBUFSIZ 32 /* buffer for records */ #define SMALL_PAGESIZE 512 /* small page size */ #define BIG_PAGESIZE 65536 /* maximum page size */ #define BIG_CACHESIZE (rnum * 2 * 15) /* maximum cache size < avail mem. */ #define SMALL_CACHESIZE (5 * 1048576) /* should be Btree fanout */ /* global variables */ const char *progname; /* program name */ int showprgr; /* whether to show progression */ /* function prototypes */ int main(int argc, char **argv); void usage(void); int runwrite(int argc, char **argv); int runread(int argc, char **argv); int runbtwrite(int argc, char **argv); int runbtread(int argc, char **argv); int myrand(void); int dowrite(char *name, int rnum); int doread(char *name, int rnum); int dobtwrite(char *name, int rnum, int rnd); int dobtread(char *name, int rnum, int rnd); /* main routine */ int main(int argc, char **argv){ int rv; progname = argv[0]; showprgr = TRUE; if(getenv("HIDEPRGR")) showprgr = FALSE; srand48(1978); if(argc < 2) usage(); rv = 0; if(!strcmp(argv[1], "write")){ rv = runwrite(argc, argv); } else if(!strcmp(argv[1], "read")){ rv = runread(argc, argv); } else if(!strcmp(argv[1], "btwrite")){ rv = runbtwrite(argc, argv); } else if(!strcmp(argv[1], "btread")){ rv = runbtread(argc, argv); } else { usage(); } return rv; } /* print the usage and exit */ void usage(void){ fprintf(stderr, "%s: test cases for Berkeley DB\n", progname); fprintf(stderr, "\n"); fprintf(stderr, "usage:\n"); fprintf(stderr, " %s write name rnum\n", progname); fprintf(stderr, " %s read name rnum\n", progname); fprintf(stderr, " %s btwrite [-rnd] name rnum\n", progname); fprintf(stderr, " %s btread [-rnd] name rnum\n", progname); fprintf(stderr, "\n"); exit(1); } /* parse arguments of write command */ int runwrite(int argc, char **argv){ char *name, *rstr; int i, rnum, rv; name = NULL; rstr = NULL; rnum = 0; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ usage(); } else if(!name){ name = argv[i]; } else if(!rstr){ rstr = argv[i]; } else { usage(); } } if(!name || !rstr) usage(); rnum = atoi(rstr); if(rnum < 1) usage(); rv = dowrite(name, rnum); return rv; } /* parse arguments of read command */ int runread(int argc, char **argv){ char *name, *rstr; int i, rnum, rv; name = NULL; rstr = NULL; rnum = 0; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ usage(); } else if(!name){ name = argv[i]; } else if(!rstr){ rstr = argv[i]; } else { usage(); } } if(!name || !rstr) usage(); rnum = atoi(rstr); if(rnum < 1) usage(); rv = doread(name, rnum); return rv; } /* parse arguments of btwrite command */ int runbtwrite(int argc, char **argv){ char *name, *rstr; int i, rnum, rnd, rv; name = NULL; rstr = NULL; rnum = 0; rnd = FALSE; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ if(!name && !strcmp(argv[i], "-rnd")){ rnd = TRUE; } else { usage(); } } else if(!name){ name = argv[i]; } else if(!rstr){ rstr = argv[i]; } else { usage(); } } if(!name || !rstr) usage(); rnum = atoi(rstr); if(rnum < 1) usage(); rv = dobtwrite(name, rnum, rnd); return rv; } /* parse arguments of btread command */ int runbtread(int argc, char **argv){ char *name, *rstr; int i, rnum, rnd, rv; name = NULL; rstr = NULL; rnum = 0; rnd = FALSE; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ if(!name && !strcmp(argv[i], "-rnd")){ rnd = TRUE; } else { usage(); } } else if(!name){ name = argv[i]; } else if(!rstr){ rstr = argv[i]; } else { usage(); } } if(!name || !rstr) usage(); rnum = atoi(rstr); if(rnum < 1) usage(); rv = dobtread(name, rnum, rnd); return rv; } /* pseudo random number generator */ int myrand(void){ static int cnt = 0; return (lrand48() + cnt++) & 0x7FFFFFFF; } /* perform write command */ int dowrite(char *name, int rnum){ DB *dbp; DBT key, data; int i, err, len; char buf[RECBUFSIZ]; if(showprgr) printf("\n name=%s rnum=%d\n\n", name, rnum); /* open a database */ if(db_create(&dbp, NULL, 0) != 0){ fprintf(stderr, "db_create failed\n"); return 1; } if(dbp->set_pagesize(dbp, SMALL_PAGESIZE) != 0){ fprintf(stderr, "DB->set_pagesize failed\n"); dbp->close(dbp, 0); return 1; } if(dbp->set_cachesize(dbp, 0, BIG_CACHESIZE, 0) != 0){ fprintf(stderr, "DB->set_cachesize failed\n"); dbp->close(dbp, 0); return 1; } if(dbp->open(dbp, NULL, name, NULL, DB_HASH, DB_CREATE | DB_TRUNCATE, 00644) != 0){ fprintf(stderr, "DB->open failed\n"); dbp->close(dbp, 0); return 1; } err = FALSE; memset(&key, 0, sizeof(key)); memset(&data, 0, sizeof(data)); /* loop for each record */ for(i = 1; i <= rnum; i++){ /* store a record */ len = sprintf(buf, "%08d", i); key.data = buf; key.size = len; data.data = buf; data.size = len; if(dbp->put(dbp, NULL, &key, &data, 0) != 0){ fprintf(stderr, "DB->put failed\n"); err = TRUE; break; } /* print progression */ if(showprgr && rnum > 250 && i % (rnum / 250) == 0){ putchar('.'); fflush(stdout); if(i == rnum || i % (rnum / 10) == 0){ printf(" (%08d)\n", i); fflush(stdout); } } } /* close the database */ if(dbp->close(dbp, 0) != 0){ fprintf(stderr, "DB->close failed\n"); err = TRUE; } if(showprgr && !err) printf("ok\n\n"); return err ? 1 : 0; } /* perform read command */ int doread(char *name, int rnum){ DB *dbp; DBT key, data; int i, err, len; char buf[RECBUFSIZ]; if(showprgr) printf("\n name=%s rnum=%d\n\n", name, rnum); /* open a database */ if(db_create(&dbp, NULL, 0) != 0){ fprintf(stderr, "db_create failed\n"); return 1; } if(dbp->set_cachesize(dbp, 0, BIG_CACHESIZE, 0) != 0){ fprintf(stderr, "DB->set_cachesize failed\n"); dbp->close(dbp, 0); return 1; } if(dbp->open(dbp, NULL, name, NULL, DB_HASH, DB_RDONLY, 00644) != 0){ fprintf(stderr, "DB->open failed\n"); dbp->close(dbp, 0); return 1; } err = FALSE; memset(&key, 0, sizeof(key)); memset(&data, 0, sizeof(data)); /* loop for each record */ for(i = 1; i <= rnum; i++){ /* store a record */ len = sprintf(buf, "%08d", i); key.data = buf; key.size = len; if(dbp->get(dbp, NULL, &key, &data, 0) != 0){ fprintf(stderr, "DB->get failed\n"); err = TRUE; break; } /* print progression */ if(showprgr && rnum > 250 && i % (rnum / 250) == 0){ putchar('.'); fflush(stdout); if(i == rnum || i % (rnum / 10) == 0){ printf(" (%08d)\n", i); fflush(stdout); } } } /* close the database */ if(dbp->close(dbp, 0) != 0){ fprintf(stderr, "DB->close failed\n"); err = TRUE; } if(showprgr && !err) printf("ok\n\n"); return err ? 1 : 0; } /* perform btwrite command */ int dobtwrite(char *name, int rnum, int rnd){ DB *dbp; DBT key, data; int i, err, len; char buf[RECBUFSIZ]; if(showprgr) printf("\n name=%s rnum=%d\n\n", name, rnum); /* open a database */ if(db_create(&dbp, NULL, 0) != 0){ fprintf(stderr, "db_create failed\n"); return 1; } if(dbp->set_pagesize(dbp, BIG_PAGESIZE) != 0){ fprintf(stderr, "DB->set_pagesize failed\n"); dbp->close(dbp, 0); return 1; } if(dbp->set_cachesize(dbp, 0, rnd ? BIG_CACHESIZE : SMALL_CACHESIZE, 0) != 0){ fprintf(stderr, "DB->set_cachesize failed\n"); dbp->close(dbp, 0); return 1; } if(dbp->open(dbp, NULL, name, NULL, DB_BTREE, DB_CREATE | DB_TRUNCATE, 00644) != 0){ fprintf(stderr, "DB->open failed\n"); dbp->close(dbp, 0); return 1; } err = FALSE; memset(&key, 0, sizeof(key)); memset(&data, 0, sizeof(data)); /* loop for each record */ for(i = 1; i <= rnum; i++){ /* store a record */ len = sprintf(buf, "%08d", rnd ? myrand() % rnum + 1 : i); key.data = data.data = buf; key.size = data.size = len; if(dbp->put(dbp, NULL, &key, &data, 0) != 0){ fprintf(stderr, "DB->put failed\n"); err = TRUE; break; } /* print progression */ if(showprgr && rnum > 250 && i % (rnum / 250) == 0){ putchar('.'); fflush(stdout); if(i == rnum || i % (rnum / 10) == 0){ printf(" (%08d)\n", i); fflush(stdout); } } } /* close the database */ if(dbp->close(dbp, 0) != 0){ fprintf(stderr, "DB->close failed\n"); err = TRUE; } if(showprgr && !err) printf("ok\n\n"); return err ? 1 : 0; } /* perform btread command */ int dobtread(char *name, int rnum, int rnd){ DB *dbp; DBT key, data; int i, err, len; char buf[RECBUFSIZ]; if(showprgr) printf("\n name=%s rnum=%d\n\n", name, rnum); /* open a database */ if(db_create(&dbp, NULL, 0) != 0){ fprintf(stderr, "db_create failed\n"); return 1; } if(dbp->set_cachesize(dbp, 0, rnd ? BIG_CACHESIZE : SMALL_CACHESIZE, 0) != 0){ fprintf(stderr, "DB->set_cachesize failed\n"); dbp->close(dbp, 0); return 1; } if(dbp->open(dbp, NULL, name, NULL, DB_BTREE, DB_RDONLY, 00644) != 0){ fprintf(stderr, "DB->open failed\n"); dbp->close(dbp, 0); return 1; } err = FALSE; memset(&key, 0, sizeof(key)); memset(&data, 0, sizeof(data)); /* loop for each record */ for(i = 1; i <= rnum; i++){ /* store a record */ len = sprintf(buf, "%08d", rnd ? myrand() % rnum + 1 : i); key.data = buf; key.size = len; if(dbp->get(dbp, NULL, &key, &data, 0) != 0){ fprintf(stderr, "DB->get failed\n"); err = TRUE; break; } /* print progression */ if(showprgr && rnum > 250 && i % (rnum / 250) == 0){ putchar('.'); fflush(stdout); if(i == rnum || i % (rnum / 10) == 0){ printf(" (%08d)\n", i); fflush(stdout); } } } /* close the database */ if(dbp->close(dbp, 0) != 0){ fprintf(stderr, "DB->close failed\n"); err = TRUE; } if(showprgr && !err) printf("ok\n\n"); return err ? 1 : 0; } /* END OF FILE */ qdbm-1.8.78/perl/0000755000175000017500000000000011426320066012506 5ustar mikiomikioqdbm-1.8.78/perl/plspex.html0000644000175000017500000002361611426311525014717 0ustar mikiomikio Specifications of QDBM for Perl

Specifications of QDBM for Perl

Copyright (C) 2000-2006 Mikio Hirabayashi
Last Update: Thu, 26 Oct 2006 15:00:20 +0900

Table of Contents

  1. Overview
  2. Installation
  3. Examples
  4. Bugs

Overview

QDBM provides API for Perl. This encapsulates the basic API, the extended API and the advanced API of QDBM. These APIs are implemented with the APIs for C called with XS language. There are two kinds of interfaces to handle a database: using methods directly and using tying functions with a hash.

In case of using methods, you call the constructor `new' of the class `Depot', `Curia' or `Villa' to open a database file or directory and get the handle. The method `close' is used in order to close the database. If the instance is destroyed without closing the database explicitly, the destructor closes the database. The method `put' is used in order to store a record. The method `out' is used in order to delete a record. The method `get' is used in order to retrieve a record. Besides, most operations like ones of the APIs for C are available.

In case of using tying functions, you call the `tie' function whose parameters are the same as ones of the constructor. After tying, operations with the tied hash perform as operations to the binded database. You use the `untie' function to close the database.

Although keys and values of storing records are treated as strings, binary data can be stored as they are. `Depot' realizes a hash database with a file. `Curia' realizes a hash database with a directory and multiple files. `Villa' realizes a B+ tree database with a file. `Depot' is fastest. `Curia' is most scalable. `Villa' provides cursor supporting ordering access.

For more information about the APIs, read documents in the sub directory `plapidoc'.


Installation

Make sure that Perl 5.6.0 or later version is installed and make sure that QDBM is installed under `/usr/local'.

Change the current working directory to the sub directory named `perl'.

cd perl

Run the configuration script.

./configure

Build programs.

make

Perform self-diagnostic test.

make check

Install programs. This operation must be carried out by the root user.

make install

When a series of work finishes, `Depot.so', `Depot.pm', `Curia.so', `Curia.pm', `Villa.so', `Villa.pm', and so on are installed under an appropriate directory according to the install directory of Perl. Executable commands `pldptest', `plcrtest', and `plvltest' will be installed in `/usr/local/bin'.

To uninstall them, execute the following command after `./configure'. This operation must be carried out by the root user.

make uninstall

Examples

The following example stores and retrieves a phone number, using the name as the key.

use Depot;

use constant NAME => "mikio";
use constant NUMBER => "000-1234-5678";
use constant DBNAME => "book";

sub main {
    my($depot, $val);

    # open the database
    if(!($depot = new Depot(&DBNAME, Depot::OWRITER | Depot::OCREAT))){
        printf(STDERR "new failed: %s\n", $Depot::errmsg);
        return 1;
    }

    # store the record
    if(!$depot->put(&NAME, &NUMBER)){
        printf(STDERR "put failed: %s\n", $Depot::errmsg);
    }

    # retrieve the record
    if(!($val = $depot->get(&NAME))){
        printf(STDERR "get failed: %s\n", $Depot::errmsg);
    } else {
        printf("Name: %s\n", &NAME);
        printf("Number: %s\n", $val);
    }

    # close the database
    if(!$depot->close()){
        printf(STDERR "close failed: %s\n", $Depot::errmsg);
        return 1;
    }

    return 0;
}

exit(main());

The following example is a transcription of the one above, using tying functions.

use Depot;

use constant NAME => "mikio";
use constant NUMBER => "000-1234-5678";
use constant DBNAME => "book";

sub main {
    my(%hash, $val);

    # open the database
    if(!tie(%hash, "Depot", &DBNAME, Depot::OWRITER | Depot::OCREAT)){
        printf(STDERR "tie failed: %s\n", $Depot::errmsg);
        return 1;
    }

    # store the record
    if(!($hash{&NAME} = &NUMBER)){
        printf(STDERR "store failed: %s\n", $Depot::errmsg);
    }

    # retrieve the record
    if(!($val = $hash{&NAME})){
        printf(STDERR "fetch failed: %s\n", $Depot::errmsg);
    } else {
        printf("Name: %s\n", &NAME);
        printf("Number: %s\n", $val);
    }

    # close the record
    if(!untie(%hash)){
        printf(STDERR "untie failed: %s\n", $Depot::errmsg);
        return 1;
    }

    return 0;
}

exit(main());

The following example performs forward matching search for strings, using the class `Villa'.

use Villa;

use constant DBNAME => "words";
use constant PREFIX => "apple";

sub main {
    my($villa, $key, $val);

    # open the database
    if(!($villa = new Villa(&DBNAME, Villa::OWRITER | Villa::OCREAT))){
        printf(STDERR "new failed: %s\n", $Villa::errmsg);
        return 1;
    }

    # store the record
    if(!$villa->put("applet", "little application", Villa::DDUP) ||
       !$villa->put("aurora", "polar wonderwork", Villa::DDUP) ||
       !$villa->put("apple", "delicious fruit", Villa::DDUP) ||
       !$villa->put("amigo", "good friend", Villa::DDUP) ||
       !$villa->put("apple", "big city", Villa::DDUP)){
        printf(STDERR "put failed: %s\n", $Villa::errmsg);
    }

    # set the cursor at the top of candidates
    $villa->curjump(&PREFIX);

    # scan with the cursor
    while($key = $villa->curkey()){
        my($prefix) = &PREFIX;
        ($key =~ m/^$prefix/) || last;
        $val = $villa->curval();
        printf("%s: %s\n", $key, $val);
        $villa->curnext();
    }

    # close the database
    if(!$villa->close()){
        printf(STDERR "close failed: %s\n", $Villa::errmsg);
        return 1;
    }

    return 0;
}

exit(main());

Bugs

So far, this API is not associated with AnyDBM_File.

This API can be implemented more effectively by Perl hackers.

For the sake of simplicity of interface, Curia for Perl does not feature handling large objects, and Villa for Perl can not be binded with a comparing function defined by users.


qdbm-1.8.78/perl/plapidoc/0000755000175000017500000000000011426320066014301 5ustar mikiomikioqdbm-1.8.78/perl/plapidoc/Villa.pm.html0000644000175000017500000003666011426320066016664 0ustar mikiomikio Villa (QDBM for Perl)

API of Villa


use Villa;
Module `Villa' should be loaded in application codes. An instance of the class `Villa' is used as a database handle.
$Villa::errmsg;
Global Variable: The message of the last happened error.
$villa = new Villa($name, $omode, $cmode);
Constructor: Get the database handle. `$name' specifies the name of a database file. `$omode' specifies the connection mode: `Villa::OWRITER' as a writer, `Villa::OREADER' as a reader. If the mode is `Villa::OWRITER', the following may be added by bitwise or: `Villa::OCREAT', which means it creates a new database if not exist, `Villa::OTRUNC', which means it creates a new database regardless if one exists, `Villa::OZCOMP', which means leaves in the database are compressed with ZLIB, `Villa::OYCOMP', which means leaves in the database are compressed with LZO, `Villa::OXCOMP', which means leaves in the database are compressed with BZIP2. Both of `Villa::OREADER' and `Villa::OWRITER' can be added to by bitwise or: `Villa::ONOLCK', which means it opens a database file without file locking, or `Villa::OLCKNB', which means locking is performed without blocking. If it is undef, `Villa::OREADER' is specified. `$cmode' specifies the comparing function: `Villa::CMPLEX' comparing keys in lexical order, `Villa::CMPDEC' comparing keys as decimal strings. The comparing function should be kept same in the life of a database. The return value is the database handle or undef if it is not successful. While connecting as a writer, an exclusive lock is invoked to the database file. While connecting as a reader, a shared lock is invoked to the database file. The thread blocks until the lock is achieved. `Villa::OZCOMP', `Villa::OYCOMP', and `Villa::OXCOMP' are available only if QDBM was built each with ZLIB, LZO, and BZIP2 enabled. If `Villa::ONOLCK' is used, the application is responsible for exclusion control.
$bool = $villa->close();
Method: Close the database handle. If successful, the return value is true, else, it is false. Because the region of a closed handle is released, it becomes impossible to use the handle. Updating a database is assured to be written when the handle is closed. If a writer opens a database but does not close it appropriately, the database will be broken. If the transaction is activated and not committed, it is aborted.
$bool = $villa->put($key, $val, $dmode);
Method: Store a record. `$key' specifies a key. If it is undef, this method has no effect. `$val' specifies a value. If it is undef, this method has no effect. `$dmode' specifies behavior when the key overlaps, by the following values: `Villa::DOVER', which means the specified value overwrites the existing one, `Villa::DKEEP', which means the existing value is kept, `Villa::DCAT', which means the specified value is concatenated at the end of the existing value, `Villa::DDUP', which means duplication of keys is allowed and the specified value is added as the last one, `Villa::DDUPR', which means duplication of keys is allowed and the specified value is added as the first one. If it is undef, `Villa::DOVER' is specified. If successful, the return value is true, else, it is false. The cursor becomes unavailable due to updating database.
$bool = $villa->out($key);
Method: Delete a record. `$key' specifies a key. If it is undef, this method has no effect. If successful, the return value is true, else, it is false. False is returned when no record corresponds to the specified key. When the key of duplicated records is specified, the first record of the same key is deleted. The cursor becomes unavailable due to updating database.
$str = $villa->get($key);
Method: Retrieve a record. `$key' specifies a key. If it is undef, this method has no effect. If successful, the return value is a scalar of the value of the corresponding record, else, it is undef. undef is returned when no record corresponds to the specified key. When the key of duplicated records is specified, the value of the first record of the same key is selected.
$num = $villa->vsiz($key);
Method: Get the size of the value of a record. `$key' specifies a key. If it is undef, this method has no effect. The return value is the size of the value of the corresponding record. If no record corresponds, -1 is returned. If multiple records correspond, the size of the first is returned.
$num = $villa->vnum($key);
Method: Get the number of records corresponding a key. `$key' specifies a key. If it is undef, this method has no effect. If successful, the return value is the size of the value of the corresponding record, else, it is 0.
$bool = $villa->curfirst();
Method: Move the cursor to the first record. If successful, the return value is true, else, it is false. False is returned if there is no record in the database.
$bool = $villa->curlast();
Method: Move the cursor to the last record. If successful, the return value is true, else, it is false. False is returned if there is no record in the database.
$bool = $villa->curprev();
Method: Move the cursor to the previous record. If successful, the return value is true, else, it is false. False is returned if there is no previous record.
$bool = $villa->curnext();
Method: Move the cursor to the next record. If successful, the return value is true, else, it is false. False is returned if there is no next record.
$bool = $villa->curjump($key, $jmode);
Method: Move the cursor to a position around a record. `$key' specifies a key. If it is undef, this method has no effect. `$jmode' specifies detail adjustment: `Villa::JFORWARD', which means that the cursor is set to the first record of the same key and that the cursor is set to the next substitute if completely matching record does not exist, `Villa::JBACKWARD', which means that the cursor is set to the last record of the same key and that the cursor is set to the previous substitute if completely matching record does not exist. If it is undef, `Villa::JFORWARD' is specified. If successful, the return value is true, else, it is false. False is returned if there is no record corresponding the condition.
$str = $villa->curkey();
Method: Get the key of the record where the cursor is. If successful, the return value is a scalar of the key of the corresponding record, else, it is undef. undef is returned when no record corresponds to the cursor.
$str = $villa->curval();
Method: Get the value of the record where the cursor is. If successful, the return value is a scalar of the value of the corresponding record, else, it is undef. undef is returned when no record corresponds to the cursor.
$bool = $villa->curput($val, $cpmode);
Method: Insert a record around the cursor. `$val' specifies a value. If it is undef, this method has no effect. `$cpmode' specifies detail adjustment: `Villa::CPCURRENT', which means that the value of the current record is overwritten, `Villa::CPBEFORE', which means that a new record is inserted before the current record, `Villa::CPAFTER', which means that a new record is inserted after the current record. If it is undef, `Villa::CPCURRENT' is specified. If successful, the return value is true, else, it is false. False is returned when no record corresponds to the cursor. After insertion, the cursor is moved to the inserted record.
$bool = $villa->curout();
Method: Delete the record where the cursor is. If successful, the return value is true, else, it is false. False is returned when no record corresponds to the cursor. After deletion, the cursor is moved to the next record if possible.
$bool = $villa->settuning($lrecmax, $nidxmax, $lcnum, $ncnum);
Method: Set alignment of the database handle. `$lrecmax' specifies the max number of records in a leaf node of B+ tree. If it is undef or not more than 0, the default value is specified. `$nidxmax' specifies the max number of indexes in a non-leaf node of B+ tree. If it is undef or not more than 0, the default value is specified. `$lcnum' specifies the max number of caching leaf nodes. If it is undef or not more than 0, the default value is specified. `$ncnum' specifies the max number of caching non-leaf nodes. If it is undef or not more than 0, the default value is specified. If successful, the return value is true, else, it is false. The default setting is equivalent to `vlsettuning(49, 192, 1024, 512)'. Because tuning parameters are not saved in a database, you should specify them every opening a database.
$bool = $villa->sync();
Method: Synchronize updating contents with the file and the device. If successful, the return value is true, else, it is false. This method is useful when another process uses the connected database file. This method should not be used while the transaction is activated.
$bool = $villa->optimize();
Method: Optimize the database. If successful, the return value is true, else, it is false. In an alternating succession of deleting and storing with overwrite or concatenate, dispensable regions accumulate. This method is useful to do away with them. This method should not be used while the transaction is activated.
$num = $villa->fsiz();
Method: Get the size of the database file. If successful, the return value is the size of the database file, else, it is -1. Because of the I/O buffer, the return value may be less than the real size.
$num = $villa->rnum();
Method: Get the number of the records stored in the database. If successful, the return value is the number of the records stored in the database, else, it is -1.
$bool = $villa->writable();
Method: Check whether the database handle is a writer or not. The return value is true if the handle is a writer, false if not.
$bool = $villa->fatalerror();
Method: Check whether the database has a fatal error or not. The return value is true if the database has a fatal error, false if not.
$bool = $villa->tranbegin();
Method: Begin the transaction. If successful, the return value is true, else, it is false. Only one transaction can be activated with a database handle at the same time.
$bool = $villa->trancommit();
Method: Commit the transaction. If successful, the return value is true, else, it is false. Updating a database in the transaction is fixed when it is committed successfully.
$bool = $villa->tranabort();
Method: Abort the transaction. If successful, the return value is true, else, it is false. Updating a database in the transaction is discarded when it is aborted. The state of the database is rollbacked to before transaction.
Called automatically by the garbage collector.
Destructor: DESTROY: Release the resources. If the database handle is not closed yet, it is closed.
$villa = tie(%hash, "Villa", $name, $omode, $cmp);
Tying Function: TIEHASH: Get the database handle.
$bool = ($hash{$key} = $val);
Tying Function: STORE: Store a record with overwrite.
$bool = delete($hash{$key});
Tying Function: DELETE: Delete a record.
$bool = (%hash = ());
Tying Function: CLEAR: Delete all records.
$str = $hash{$key};
Tying Function: FETCH: Retrieve whole value of a record.
$bool = exists($hash{$val});
Tying Function: EXISTS: Check whether a record exists or not.
Called automatically by keys(), each(), and so on.
Tying Function: FIRSTKEY: Get the first key.
Called automatically by keys(), each(), and so on.
Tying Function: NEXTKEY: Get the next key.
$func = $villa->filter_store_key(\&nf);
Method: set a filter invoked when writing a key. `\&nf' specifies the reference of a filter function proofing `$_'. If it is undef, the current filter function is cleared. The return value is the old filter function.
$func = $villa->filter_store_value(\&nf);
Method: set a filter invoked when writing a value. `\&nf' specifies the reference of a filter function proofing `$_'. If it is undef, the current filter function is cleared. The return value is the old filter function.
$func = $villa->filter_fetch_key(\&nf);
Method: set a filter invoked when reading a key. `\&nf' specifies the reference of a filter function proofing `$_'. If it is undef, the current filter function is cleared. The return value is the old filter function.
$func = $villa->filter_fetch_value(\&nf);
Method: set a filter invoked when reading a value. `\&nf' specifies the reference of a filter function proofing `$_'. If it is undef, the current filter function is cleared. The return value is the old filter function.

Generated by mypldoc, 2010/08/05.
qdbm-1.8.78/perl/plapidoc/Depot.pm.html0000644000175000017500000003005011426320066016653 0ustar mikiomikio Depot (QDBM for Perl)

API of Depot


use Depot;
Module `Depot' should be loaded in application codes. An instance of the class `Depot' is used as a database handle.
$Depot::errmsg;
Global Variable: The message of the last happened error.
$depot = new Depot($name, $omode, $bnum);
Constructor: Get the database handle. `$name' specifies the name of a database file. `$omode' specifies the connection mode: `Depot::OWRITER' as a writer, `Depot::OREADER' as a reader. If the mode is `Depot::OWRITER', the following may be added by bitwise or: `Depot::OCREAT', which means it creates a new database if not exist, `Depot::OTRUNC', which means it creates a new database regardless if one exists. Both of `Depot::OREADER' and `Depot::OWRITER' can be added to by bitwise or: `Depot::ONOLCK', which means it opens a database file without file locking, or `Depot::OLCKNB', which means locking is performed without blocking. `Depot::OCREAT' can be added to by bitwise or: `Depot::OSPARSE', which means it creates a database file as a sparse file. If it is undef, `Depot::OREADER' is specified. `$bnum' specifies the number of elements of the bucket array. If it is undef or not more than 0, the default value is specified. The size of a bucket array is determined on creating, and can not be changed except for by optimization of the database. Suggested size of a bucket array is about from 0.5 to 4 times of the number of all records to store. The return value is the database handle or undef if it is not successful. While connecting as a writer, an exclusive lock is invoked to the database file. While connecting as a reader, a shared lock is invoked to the database file. The thread blocks until the lock is achieved. If `Depot::ONOLCK' is used, the application is responsible for exclusion control.
$bool = $depot->close();
Method: Close the database handle. If successful, the return value is true, else, it is false. Because the region of a closed handle is released, it becomes impossible to use the handle. Updating a database is assured to be written when the handle is closed. If a writer opens a database but does not close it appropriately, the database will be broken.
$bool = $depot->put($key, $val, $dmode);
Method: Store a record. `$key' specifies a key. If it is undef, this method has no effect. `$val' specifies a value. If it is undef, this method has no effect. `$dmode' specifies behavior when the key overlaps, by the following values: `Depot::DOVER', which means the specified value overwrites the existing one, `Depot::DKEEP', which means the existing value is kept, `Depot::DCAT', which means the specified value is concatenated at the end of the existing value. If it is undef, `Depot::DOVER' is specified. If successful, the return value is true, else, it is false.
$bool = $depot->out($key);
Method: Delete a record. `$key' specifies a key. If it is undef, this method has no effect. If successful, the return value is true, else, it is false. False is returned when no record corresponds to the specified key.
$str = $depot->get($key, $start, $max);
Method: Retrieve a record. `$key' specifies a key. If it is undef, this method has no effect. `$start' specifies the offset address of the beginning of the region of the value to be read. If it is negative or undef, the offset is specified as 0. `$max' specifies the max size to be read. If it is negative or undef, the size to read is unlimited. If successful, the return value is a scalar of the value of the corresponding record, else, it is undef. undef is returned when no record corresponds to the specified key or the size of the value of the corresponding record is less than `$start'.
$num = $depot->vsiz($key);
Method: Get the size of the value of a record. `$key' specifies a key. If it is undef, this method has no effect. If successful, the return value is the size of the value of the corresponding record, else, it is -1. Because this method does not read the entity of a record, it is faster than `get'.
$bool = $depot->iterinit();
Method: Initialize the iterator of the database handle. If successful, the return value is true, else, it is false. The iterator is used in order to access the key of every record stored in a database.
$str = $depot->iternext();
Method: Get the next key of the iterator. If successful, the return value is a scalar of the value of the next key, else, it is undef. undef is returned when no record is to be get out of the iterator. It is possible to access every record by iteration of calling this method. However, it is not assured if updating the database is occurred while the iteration. Besides, the order of this traversal access method is arbitrary, so it is not assured that the order of storing matches the one of the traversal access.
$bool = $depot->setalign($align);
Method: Set alignment of the database handle. `$align' specifies the basic size of alignment. If it is undef, alignment is cleared. If successful, the return value is true, else, it is false. If alignment is set to a database, the efficiency of overwriting values is improved. The size of alignment is suggested to be average size of the values of the records to be stored. If alignment is positive, padding whose size is multiple number of the alignment is placed. If alignment is negative, as `vsiz' is the size of a value, the size of padding is calculated with `(vsiz / pow(2, abs(align) - 1))'. Because alignment setting is not saved in a database, you should specify alignment every opening a database.
$bool = $depot->setfbpsiz($size);
Method: Set the size of the free block pool. `$size' specifies the size of the free block pool. If it is undef, the free block pool is not used. If successful, the return value is true, else, it is false. The default size of the free block pool is 16. If the size is greater, the space efficiency of overwriting values is improved with the time efficiency sacrificed.
$bool = $depot->sync();
Method: Synchronize updating contents with the file and the device. If successful, the return value is true, else, it is false. This method is useful when another process uses the connected database file.
$bool = $depot->optimize($bnum);
Method: Optimize the database. `$bnum' specifies the number of the elements of the bucket array. If it is undef or not more than 0, the default value is specified. If successful, the return value is true, else, it is false. In an alternating succession of deleting and storing with overwrite or concatenate, dispensable regions accumulate. This method is useful to do away with them.
$num = $depot->fsiz();
Method: Get the size of the database file. If successful, the return value is the size of the database file, else, it is -1.
$num = $depot->bnum();
Method: Get the number of the elements of the bucket array. If successful, the return value is the number of the elements of the bucket array, else, it is -1.
$num = $depot->rnum();
Method: Get the number of the records stored in the database. If successful, the return value is the number of the records stored in the database, else, it is -1.
$bool = $depot->writable();
Method: Check whether the database handle is a writer or not. The return value is true if the handle is a writer, false if not.
$bool = $depot->fatalerror();
Method: Check whether the database has a fatal error or not. The return value is true if the database has a fatal error, false if not.
Called automatically by the garbage collector.
Destructor: DESTROY: Release the resources. If the database handle is not closed yet, it is closed.
$depot = tie(%hash, "Depot", $name, $omode, $bnum);
Tying Function: TIEHASH: Get the database handle.
$bool = ($hash{$key} = $val);
Tying Function: STORE: Store a record with overwrite.
$bool = delete($hash{$key});
Tying Function: DELETE: Delete a record.
$bool = (%hash = ());
Tying Function: CLEAR: Delete all records.
$str = $hash{$key};
Tying Function: FETCH: Retrieve whole value of a record.
$bool = exists($hash{$val});
Tying Function: EXISTS: Check whether a record exists or not.
Called automatically by keys(), each(), and so on.
Tying Function: FIRSTKEY: Get the first key.
Called automatically by keys(), each(), and so on.
Tying Function: NEXTKEY: Get the next key.
$func = $depot->filter_store_key(\&nf);
Method: set a filter invoked when writing a key. `\&nf' specifies the reference of a filter function proofing `$_'. If it is undef, the current filter function is cleared. The return value is the old filter function.
$func = $depot->filter_store_value(\&nf);
Method: set a filter invoked when writing a value. `\&nf' specifies the reference of a filter function proofing `$_'. If it is undef, the current filter function is cleared. The return value is the old filter function.
$func = $depot->filter_fetch_key(\&nf);
Method: set a filter invoked when reading a key. `\&nf' specifies the reference of a filter function proofing `$_'. If it is undef, the current filter function is cleared. The return value is the old filter function.
$func = $depot->filter_fetch_value(\&nf);
Method: set a filter invoked when reading a value. `\&nf' specifies the reference of a filter function proofing `$_'. If it is undef, the current filter function is cleared. The return value is the old filter function.

Generated by mypldoc, 2010/08/05.
qdbm-1.8.78/perl/plapidoc/index.html0000644000175000017500000000667711426320066016316 0ustar mikiomikio INDEX (QDBM for Perl)
Perl Source Documents

QDBM for Perl


Overview

QDBM is a library of routines for managing a database. The database is a simple data file containing records, each is a pair of a key and a value. Every key and value is serial bytes with variable length. Both binary data and character string can be used as a key and a value. There is neither concept of data tables nor data types. Records are organazed in hash table or B+ tree.

As for database of hash table, each key must be unique within a database, so it is impossible to store two or more records with a key overlaps. The following access methods are provided to the database: storing a record with a key and a value, deleting a record by a key, retrieving a record by a key. Moreover, traversal access to every key are provided, although the order is arbitrary. These access methods are similar to ones of DBM (or its followers, NDBM and GDBM) library defined in the UNIX standard. QDBM is an alternative for DBM because of its higher performance.

As for database of B+ tree, records whose keys are duplicated can be stored. Access methods of storing, deleting and retrieving are provided as with the database of hash table. Records are stored in order by a comparing function assigned by a user. It is possible to access each record with the cursor in ascending or descending order. According to this mechanism, forward matching search for strings and range search for integers are realized.

QDBM provides API for Perl. This encapsulates the basic API, the extended API and the advanced API of QDBM. A database handle can be used as a hash variable.

Refer to `http://fallabs.com/qdbm/' for more information.


API


Generated by mypldoc, 2010/08/05.
qdbm-1.8.78/perl/plapidoc/Curia.pm.html0000644000175000017500000003061411426320066016651 0ustar mikiomikio Curia (QDBM for Perl)

API of Curia


use Curia;
Module `Curia' should be loaded in application codes. An instance of the class `Curia' is used as a database handle.
$Curia::errmsg;
Global Variable: The message of the last happened error.
$curia = new Curia($name, $omode, $bnum, $dnum);
Constructor: Get the database handle. `$name' specifies the name of a database directory. `$omode' specifies the connection mode: `Curia::OWRITER' as a writer, `Curia::OREADER' as a reader. If the mode is `Curia::OWRITER', the following may be added by bitwise or: `Curia::OCREAT', which means it creates a new database if not exist, `Curia::OTRUNC', which means it creates a new database regardless if one exists. Both of `Curia::OREADER' and `Curia::OWRITER' can be added to by bitwise or: `Curia::ONOLCK', which means it opens a database directory without file locking, or `Curia::OLCKNB', which means locking is performed without blocking. `Curia::OCREAT' can be added to by bitwise or: `Curia::OSPARSE', which means it creates database files as sparse files. If it is undef, `Curia::OREADER' is specified. `$bnum' specifies the number of elements of the bucket array. If it is undef or not more than 0, the default value is specified. The size of a bucket array is determined on creating, and can not be changed except for by optimization of the database. Suggested size of a bucket array is about from 0.5 to 4 times of the number of all records to store. `$dnum' specifies the number of division of the database. If it is undef or not more than 0, the default value is specified. The number of division can not be changed from the initial value. The max number of division is 512. The return value is the database handle or undef if it is not successful. While connecting as a writer, an exclusive lock is invoked to the database directory. While connecting as a reader, a shared lock is invoked to the database directory. The thread blocks until the lock is achieved. If `Curia::ONOLCK' is used, the application is responsible for exclusion control.
$bool = $curia->close();
Method: Close the database handle. If successful, the return value is true, else, it is false. Because the region of a closed handle is released, it becomes impossible to use the handle. Updating a database is assured to be written when the handle is closed. If a writer opens a database but does not close it appropriately, the database will be broken.
$bool = $curia->put($key, $val, $dmode);
Method: Store a record. `$key' specifies a key. If it is undef, this method has no effect. `$val' specifies a value. If it is undef, this method has no effect. `$dmode' specifies behavior when the key overlaps, by the following values: `Curia::DOVER', which means the specified value overwrites the existing one, `Curia::DKEEP', which means the existing value is kept, `Curia::DCAT', which means the specified value is concatenated at the end of the existing value. If it is undef, `Curia::DOVER' is specified. If successful, the return value is true, else, it is false.
$bool = $curia->out($key);
Method: Delete a record. `$key' specifies a key. If it is undef, this method has no effect. If successful, the return value is true, else, it is false. False is returned when no record corresponds to the specified key.
$str = $curia->get($key, $start, $max);
Method: Retrieve a record. `$key' specifies a key. If it is undef, this method has no effect. `$start' specifies the offset address of the beginning of the region of the value to be read. If it is negative or undef, the offset is specified as 0. `$max' specifies the max size to be read. If it is negative or undef, the size to read is unlimited. If successful, the return value is a scalar of the value of the corresponding record, else, it is undef. undef is returned when no record corresponds to the specified key or the size of the value of the corresponding record is less than `$start'.
$num = $curia->vsiz($key);
Method: Get the size of the value of a record. `$key' specifies a key. If it is undef, this method has no effect. If successful, the return value is the size of the value of the corresponding record, else, it is -1. Because this method does not read the entity of a record, it is faster than `get'.
$bool = $curia->iterinit();
Method: Initialize the iterator of the database handle. If successful, the return value is true, else, it is false. The iterator is used in order to access the key of every record stored in a database.
$str = $curia->iternext();
Method: Get the next key of the iterator. If successful, the return value is a scalar of the value of the next key, else, it is undef. undef is returned when no record is to be get out of the iterator. It is possible to access every record by iteration of calling this method. However, it is not assured if updating the database is occurred while the iteration. Besides, the order of this traversal access method is arbitrary, so it is not assured that the order of storing matches the one of the traversal access.
$bool = $curia->setalign($align);
Method: Set alignment of the database handle. `$align' specifies the basic size of alignment. If it is undef, alignment is cleared. If successful, the return value is true, else, it is false. If alignment is set to a database, the efficiency of overwriting values is improved. The size of alignment is suggested to be average size of the values of the records to be stored. If alignment is positive, padding whose size is multiple number of the alignment is placed. If alignment is negative, as `vsiz' is the size of a value, the size of padding is calculated with `(vsiz / pow(2, abs(align) - 1))'. Because alignment setting is not saved in a database, you should specify alignment every opening a database.
$bool = $curia->setfbpsiz($size);
Method: Set the size of the free block pool. `$size' specifies the size of the free block pool. If it is undef, the free block pool is not used. If successful, the return value is true, else, it is false. The default size of the free block pool is 16. If the size is greater, the space efficiency of overwriting values is improved with the time efficiency sacrificed.
$bool = $curia->sync();
Method: Synchronize updating contents with the files and the devices. If successful, the return value is true, else, it is false. This method is useful when another process uses the connected database directory.
$bool = $curia->optimize($bnum);
Method: Optimize the database. `$bnum' specifies the number of the elements of the bucket array. If it is undef or not more than 0, the default value is specified. If successful, the return value is true, else, it is false. In an alternating succession of deleting and storing with overwrite or concatenate, dispensable regions accumulate. This method is useful to do away with them.
$num = $curia->fsiz();
Method: Get the total size of the database files. If successful, the return value is the total size of the database files, else, it is -1. If the total size is more than 2GB, the return value overflows.
$num = $curia->bnum();
Method: Get the total number of the elements of each bucket array. If successful, the return value is the total number of the elements of each bucket array, else, it is -1.
$num = $curia->rnum();
Method: Get the number of the records stored in the database. If successful, the return value is the number of the records stored in the database, else, it is -1.
$bool = $curia->writable();
Method: Check whether the database handle is a writer or not. The return value is true if the handle is a writer, false if not.
$bool = $curia->fatalerror();
Method: Check whether the database has a fatal error or not. The return value is true if the database has a fatal error, false if not.
Called automatically by the garbage collector.
Destructor: DESTROY: Release the resources. If the database handle is not closed yet, it is closed.
$curia = tie(%hash, "Curia", $name, $omode, $bnum, $dnum);
Tying Function: TIEHASH: Get the database handle.
$bool = ($hash{$key} = $val);
Tying Function: STORE: Store a record with overwrite.
$bool = delete($hash{$key});
Tying Function: DELETE: Delete a record.
$bool = (%hash = ());
Tying Function: CLEAR: Delete all records.
$str = $hash{$key};
Tying Function: FETCH: Retrieve whole value of a record.
$bool = exists($hash{$val});
Tying Function: EXISTS: Check whether a record exists or not.
Called automatically by keys(), each(), and so on.
Tying Function: FIRSTKEY: Get the first key.
Called automatically by keys(), each(), and so on.
Tying Function: NEXTKEY: Get the next key.
$func = $curia->filter_store_key(\&nf);
Method: set a filter invoked when writing a key. `\&nf' specifies the reference of a filter function proofing `$_'. If it is undef, the current filter function is cleared. The return value is the old filter function.
$func = $curia->filter_store_value(\&nf);
Method: set a filter invoked when writing a value. `\&nf' specifies the reference of a filter function proofing `$_'. If it is undef, the current filter function is cleared. The return value is the old filter function.
$func = $curia->filter_fetch_key(\&nf);
Method: set a filter invoked when reading a key. `\&nf' specifies the reference of a filter function proofing `$_'. If it is undef, the current filter function is cleared. The return value is the old filter function.
$func = $curia->filter_fetch_value(\&nf);
Method: set a filter invoked when reading a value. `\&nf' specifies the reference a filter function proofing `$_'. If it is undef, the current filter function is cleared. The return value is the old filter function.

Generated by mypldoc, 2010/08/05.
qdbm-1.8.78/perl/Makefile.in0000644000175000017500000001025410525610404014552 0ustar mikiomikio# Makefile for Perl interface of QDBM #================================================================ # Setting variables #================================================================ # Generic settings SHELL = @SHELL@ # Packaging PACKAGE = qdbm # Targets MYBINS = depot/pldptest curia/plcrtest villa/plvltest MYDOCS = plspex.html plspex-ja.html plapidoc # Install destinations prefix = @prefix@ exec_prefix = @exec_prefix@ MYBINDIR = @bindir@ MYDATADIR = @datadir@/$(PACKAGE)/perl DESTDIR = # Building binaries CC = gcc INC = -I. -I../.. -I$(HOME)/include -I/usr/local/include OPTIMIZE = -O2 LD = gcc LIBS = -L../.. -I$(HOME)/lib -L/usr/local/lib -lqdbm @LIBS@ RUNENV = LD_LIBRARY_PATH=.:..:../..:/usr/local/lib:$(HOME)/lib #================================================================ # Actions #================================================================ all : cd depot && [ -f Makefile ] || \ $(RUNENV) perl Makefile.PL CC="$(CC)" INC="$(INC)" OPTIMIZE="$(OPTIMIZE)" \ LD="$(LD)" LIBS="$(LIBS)" PREFIX="$(prefix)" ; \ $(RUNENV) make cd curia && [ -f Makefile ] || \ $(RUNENV) perl Makefile.PL CC="$(CC)" INC="$(INC)" OPTIMIZE="$(OPTIMIZE)" \ LD="$(LD)" LIBS="$(LIBS)" PREFIX="$(prefix)" ; \ $(RUNENV) make cd villa && [ -f Makefile ] || \ $(RUNENV) perl Makefile.PL CC="$(CC)" INC="$(INC)" OPTIMIZE="$(OPTIMIZE)" \ LD="$(LD)" LIBS="$(LIBS)" PREFIX="$(prefix)" ; \ $(RUNENV) make @printf '\n' @printf '#================================================================\n' @printf '# Ready to install.\n' @printf '#================================================================\n' clean : cd depot && if [ -f Makefile ] ; then $(RUNENV) make -i clean ; fi || true cd depot && rm -rf Makefile blib pm_to_blib *.c *.o *.bs *.old casket *~ cd curia && if [ -f Makefile ] ; then $(RUNENV) make -i clean ; fi || true cd curia && rm -rf Makefile blib pm_to_blib *.c *.o *.bs *.old casket *~ cd villa && if [ -f Makefile ] ; then $(RUNENV) make -i clean ; fi || true cd villa && rm -rf Makefile blib pm_to_blib *.c *.o *.bs *.old casket *~ rm -rf casket *~ install : cd depot && $(RUNENV) make install cd curia && $(RUNENV) make install cd villa && $(RUNENV) make install mkdir -p $(DESTDIR)$(MYBINDIR) cp -f $(MYBINS) $(DESTDIR)$(MYBINDIR) mkdir -p $(DESTDIR)$(MYDATADIR) cp -Rf $(MYDOCS) $(DESTDIR)$(MYDATADIR) @printf '\n' @printf '#================================================================\n' @printf '# Thanks for using QDBM for Perl.\n' @printf '#================================================================\n' uninstall : pprefix=`perl -e 'foreach(@INC){ print "$$_\n"; }' | grep -v '^\.'` ; \ find $$pprefix -print | sort | uniq | egrep '(Depot|Curia|Villa)' | xargs rm -rf for file in $(MYBINS) ; \ do \ file=`printf '%s' $$file | sed 's/.*\///'` ; \ if [ -n "$$file" ] ; then rm -f "$(DESTDIR)$(MYBINDIR)/$$file" ; fi ; \ done rm -rf $(DESTDIR)$(MYDATADIR) check : sync ; sync cd depot && rm -rf casket cd depot && \ $(RUNENV) perl -w pldptest write casket 10000 1000 cd depot && \ $(RUNENV) perl -w pldptest read casket cd depot && \ $(RUNENV) perl -w pldptest tie casket cd depot && rm -rf casket cd curia && rm -rf casket cd curia && \ $(RUNENV) perl -w plcrtest write casket 10000 100 10 cd curia && \ $(RUNENV) perl -w plcrtest read casket cd curia && \ $(RUNENV) perl -w plcrtest tie casket cd curia && rm -rf casket cd villa && rm -rf casket cd villa && \ $(RUNENV) perl -w plvltest write casket 10000 cd villa && \ $(RUNENV) perl -w plvltest read casket cd villa && \ $(RUNENV) perl -w plvltest tie casket cd villa && rm -rf casket @printf '\n' @printf '#================================================================\n' @printf '# Checking completed.\n' @printf '#================================================================\n' doc : make docclean $(RUNENV) ./mypldoc -d plapidoc -t "QDBM for Perl" -a overview \ depot/Depot.pm curia/Curia.pm villa/Villa.pm docclean : rm -rf plapidoc dist : make doc make distclean distclean : clean rm -rf Makefile config.cache config.log config.status autom4te.cache .PHONY : all clean install check # END OF FILE qdbm-1.8.78/perl/mypldoc0000755000175000017500000001462711426314425014117 0ustar mikiomikio#! /usr/bin/perl -w #================================================================ # mypldoc # Document generator for Perl sources #================================================================ use strict; use warnings; # main routine sub main { my($i, $err, $destdir, $ptitle, $afile, @files, $file); $err = 0; $ptitle = "Perl API"; for($i = 0; $i < scalar(@ARGV); $i++){ if($ARGV[$i] =~ m/^-d/){ $destdir = $ARGV[++$i]; } elsif($ARGV[$i] =~ m/^-t/){ $ptitle = $ARGV[++$i]; } elsif($ARGV[$i] =~ m/^-a/){ $afile = $ARGV[++$i]; } else { push(@files, $ARGV[$i]); } } (scalar(@files) > 0) || usage(); (defined($destdir)) || ($destdir = "."); (-d $destdir) || (mkdir($destdir)) || die "$1: $!\n"; foreach $file (@files){ (makedoc($destdir, $ptitle, $file)) || ($err = 1); } (makeindex($destdir, $ptitle, $afile, \@files)) || ($err = 1); return $err ? 1 : 0; } # print the usage and exit sub usage { printf(STDERR "$0: usage: $0 [-d dir] [-t str] [-a file] file ...\n"); exit(1); } # generate a document sub makedoc { my($destdir) = shift; my($ptitle) = shift; my($source) = shift; my($dest, $in, $out, $line, @group, $kbd, $i); if(!(-r $source)){ printf(STDERR "$0: $source: no such file\n"); return 0; } if(!open(IN, $source)){ printf(STDERR "$0: $source: cannot open\n"); return 0; } $in = *IN; $source =~ s/.*\///; $dest = ">$destdir/$source.html"; if(!open(OUT, $dest)){ printf(STDERR "$0: $dest: cannot open\n"); return 0; } $out = *OUT; writehead($out, $ptitle, $source); while(defined($line = <$in>)){ chomp($line); if($line =~ m/^\x23\x23/){ @group = (); while(defined($line = <$in>)){ chomp($line); ($line =~ m/^\x23/) || last; (length($line) > 1) || next; push(@group, $line); } if(scalar(@group) > 0){ printf($out "
\n"); $kbd = $group[0] =~ m/^\x23:/; for($i = 0; $i < scalar(@group); $i++){ $group[$i] =~ s/^\x23[ :]*//; $group[$i] =~ s/&/&/; $group[$i] =~ s//>/; $group[$i] =~ s/\x22/"/; } if($kbd){ printf($out "
%s
\n", $group[0]); } else { printf($out "
%s
\n", $group[0]); } if(scalar(@group) > 1){ printf($out "
\n"); for($i = 1; $i < scalar(@group); $i++){ printf($out "%s\n", $group[$i]); } printf($out "
\n"); } printf($out "
\n"); } } } printf($out "
\n"); writetail($out); close($out); close($in); return 1; } # generate the index file sub makeindex { my($destdir) = shift; my($ptitle) = shift; my($afile) = shift; my($filesref) = shift; my($line, @files, $dest, $in, $out, $file, $name); @files = @$filesref; $dest = ">$destdir/index.html"; if(!open(OUT, $dest)){ printf(STDERR "$0: $dest: cannot open\n"); return 0; } $out = *OUT; writehead($out, $ptitle); if(defined($afile)){ if(open(IN, $afile)){ while(defined($line = )){ chomp($line); printf(OUT "%s\n", $line); } close(IN); } else { printf(STDERR "$0: $afile: cannot open\n"); } printf($out "
\n"); } printf($out "

API

\n"); printf($out "
    \n"); foreach $file (@files){ $file =~ s/.*\///; $name = $file; $name =~ s/\..*//; printf($out "
  • $name
  • \n"); } printf($out "
\n"); printf($out "
\n"); writetail($out); close($out); return 1; } # write header sub writehead { my($out) = shift; my($ptitle) = shift; my($name) = shift; my($title, $head, $navi); if(defined($name)){ $name =~ s/\..*//; $title = "$name ($ptitle)"; $head = "API of $name"; $navi = ""; } else { $title = "INDEX ($ptitle)"; $head = "$ptitle"; $navi = "
Perl Source Documents
"; } print $out <<__MYEOF $title $navi

$head


__MYEOF } # write tail sub writetail { my($out) = shift; my($sec,$min,$hour,$mday,$mon,$year) = localtime(); my($datestr) = sprintf("%04d/%02d/%02d", $year + 1900, $mon + 1, $mday); print $out <<__MYEOF
Generated by $0, $datestr.
__MYEOF } # execute main $0 =~ s/.*\///; exit(main()); # END OF FILE qdbm-1.8.78/perl/overview0000644000175000017500000000327411426314413014304 0ustar mikiomikio

Overview

QDBM is a library of routines for managing a database. The database is a simple data file containing records, each is a pair of a key and a value. Every key and value is serial bytes with variable length. Both binary data and character string can be used as a key and a value. There is neither concept of data tables nor data types. Records are organazed in hash table or B+ tree.

As for database of hash table, each key must be unique within a database, so it is impossible to store two or more records with a key overlaps. The following access methods are provided to the database: storing a record with a key and a value, deleting a record by a key, retrieving a record by a key. Moreover, traversal access to every key are provided, although the order is arbitrary. These access methods are similar to ones of DBM (or its followers, NDBM and GDBM) library defined in the UNIX standard. QDBM is an alternative for DBM because of its higher performance.

As for database of B+ tree, records whose keys are duplicated can be stored. Access methods of storing, deleting and retrieving are provided as with the database of hash table. Records are stored in order by a comparing function assigned by a user. It is possible to access each record with the cursor in ascending or descending order. According to this mechanism, forward matching search for strings and range search for integers are realized.

QDBM provides API for Perl. This encapsulates the basic API, the extended API and the advanced API of QDBM. A database handle can be used as a hash variable.

Refer to `http://fallabs.com/qdbm/' for more information.

qdbm-1.8.78/perl/configure.in0000644000175000017500000000243110365614166015027 0ustar mikiomikio# Source of configuration for Perl interface of QDBM # Targets AC_INIT(qdbm-perl, 1.0.0) # Building paths pathtmp="$PATH" PATH="$HOME/bin:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin" PATH="$PATH:/usr/ccs/bin:/usr/ucb:/usr/xpg4/bin:/usr/xpg6/bin:$pathtmp" LIBRARY_PATH="$HOME/lib:/usr/local/lib:$LIBRARY_PATH" LD_LIBRARY_PATH="$HOME/lib:/usr/local/lib:$LD_LIBRARY_PATH" CPATH="$HOME/include:/usr/local/include:$CPATH" export PATH LIBRARY_PATH LD_LIBRARY_PATH CPATH # Setting the default prefix if test "$prefix" = NONE then prefix=`perl -mConfig -e 'print $Config::Config{prefix}'` fi # Underlying libraries AC_CHECK_LIB(c, main) AC_CHECK_LIB(pthread, main) AC_CHECK_LIB(z, main) AC_CHECK_LIB(lzo2, main) AC_CHECK_LIB(bz2, main) AC_CHECK_LIB(iconv, main) # Duplication of QDBM for Perl AC_CHECK_LIB(qdbm, main, true, printf 'checking whether /usr/local/lib/libqdbm.* is... ' if ls /usr/local/lib/libqdbm.* > /dev/null 2>&1 then printf 'yes\n' else printf 'no\n' printf '#================================================================\n' 1>&2 printf '# WARNING: Install QDBM libraries before installation.\n' 1>&2 printf '#================================================================\n' 1>&2 fi ) # Targets AC_OUTPUT(Makefile) # END OF FILE qdbm-1.8.78/perl/curia/0000755000175000017500000000000010705266453013621 5ustar mikiomikioqdbm-1.8.78/perl/curia/MANIFEST0000644000175000017500000000006007727054335014752 0ustar mikiomikioMANIFEST Makefile.PL Curia.pm Curia.xs plcrtest qdbm-1.8.78/perl/curia/Curia.pm0000644000175000017500000005074210445176512015227 0ustar mikiomikio#================================================================================================= # Perl API of Curia, the extended API of QDBM # Copyright (C) 2000-2005 Mikio Hirabayashi # This file is part of QDBM, Quick Database Manager. # QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU # Lesser General Public License as published by the Free Software Foundation; either version # 2.1 of the License or any later version. QDBM is distributed in the hope that it will be # useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more # details. # You should have received a copy of the GNU Lesser General Public License along with QDBM; if # not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA # 02111-1307 USA. #================================================================================================= package Curia; use strict; use warnings; require Tie::Hash; require Exporter; require XSLoader; our @ISA = qw(Tie::Hash Exporter); our $VERSION = '1.0'; XSLoader::load('Curia', $VERSION); use constant TRUE => 1; # boolean true use constant FALSE => 0; # boolean false use constant OREADER => 1 << 0; # open as a reader use constant OWRITER => 1 << 1; # open as a writer use constant OCREAT => 1 << 2; # a writer creating use constant OTRUNC => 1 << 3; # a writer truncating use constant ONOLCK => 1 << 4; # open without locking use constant OLCKNB => 1 << 5; # lock without blocking use constant OSPARSE => 1 << 6; # create as sparse files use constant DOVER => 0; # overwrite an existing value use constant DKEEP => 1; # keep an existing value use constant DCAT => 2; # concatenate values my(%handles) = (); # table of database names our($errmsg) = "no error"; # message of the last error #================================================================================================= # public objects #================================================================================================= ## # use Curia; # Module `Curia' should be loaded in application codes. # An instance of the class `Curia' is used as a database handle. # ## # $Curia::errmsg; # Global Variable: The message of the last happened error. # ## # $curia = new Curia($name, $omode, $bnum, $dnum); # Constructor: Get the database handle. # `$name' specifies the name of a database directory. # `$omode' specifies the connection mode: `Curia::OWRITER' as a writer, `Curia::OREADER' as a # reader. If the mode is `Curia::OWRITER', the following may be added by bitwise or: # `Curia::OCREAT', which means it creates a new database if not exist, `Curia::OTRUNC', which # means it creates a new database regardless if one exists. Both of `Curia::OREADER' and # `Curia::OWRITER' can be added to by bitwise or: `Curia::ONOLCK', which means it opens a # database directory without file locking, or `Curia::OLCKNB', which means locking is performed # without blocking. `Curia::OCREAT' can be added to by bitwise or: `Curia::OSPARSE', which means # it creates database files as sparse files. If it is undef, `Curia::OREADER' is specified. # `$bnum' specifies the number of elements of the bucket array. If it is undef or not more # than 0, the default value is specified. The size of a bucket array is determined on creating, # and can not be changed except for by optimization of the database. Suggested size of a # bucket array is about from 0.5 to 4 times of the number of all records to store. # `$dnum' specifies the number of division of the database. If it is undef or not more than 0, # the default value is specified. The number of division can not be changed from the initial # value. The max number of division is 512. # The return value is the database handle or undef if it is not successful. # While connecting as a writer, an exclusive lock is invoked to the database directory. # While connecting as a reader, a shared lock is invoked to the database directory. The thread # blocks until the lock is achieved. If `Curia::ONOLCK' is used, the application is responsible # for exclusion control. # sub new { my($class) = shift; my($name) = shift; my($omode) = shift; my($bnum) = shift; my($dnum) = shift; (defined($name) && length($name) > 0 && scalar(@_) == 0) || return undef; (!$handles{$name}) || return undef; (defined($omode)) || ($omode = OREADER); (defined($bnum)) || ($bnum = -1); (defined($dnum)) || ($dnum = -1); my($curia) = plcropen($name, $omode, $bnum, $dnum); $errmsg = plcrerrmsg(); ($curia > 0) || return undef; $handles{$name} = $curia; my $self = [$name, TRUE, undef, undef, undef, undef]; bless($self, $class); return $self; } ## # $bool = $curia->close(); # Method: Close the database handle. # If successful, the return value is true, else, it is false. # Because the region of a closed handle is released, it becomes impossible to use the handle. # Updating a database is assured to be written when the handle is closed. If a writer opens # a database but does not close it appropriately, the database will be broken. # sub close { my($self) = shift; ($$self[1]) || return FALSE; (scalar(@_) == 0) || return FALSE; $$self[1] = FALSE; my($curia) = $handles{$$self[0]}; my($rv) = plcrclose($curia); $errmsg = plcrerrmsg(); delete($handles{$$self[0]}); return $rv; } ## # $bool = $curia->put($key, $val, $dmode); # Method: Store a record. # `$key' specifies a key. If it is undef, this method has no effect. # `$val' specifies a value. If it is undef, this method has no effect. # `$dmode' specifies behavior when the key overlaps, by the following values: `Curia::DOVER', # which means the specified value overwrites the existing one, `Curia::DKEEP', which means the # existing value is kept, `Curia::DCAT', which means the specified value is concatenated at # the end of the existing value. If it is undef, `Curia::DOVER' is specified. # If successful, the return value is true, else, it is false. # sub put { my($self) = shift; ($$self[1]) || return FALSE; my($key) = shift; my($val) = shift; my($dmode) = shift; (scalar(@_) == 0) || return FALSE; (defined($key) && defined($val)) || return FALSE; (defined($dmode)) || ($dmode = DOVER); my($curia) = $handles{$$self[0]}; if($$self[2]){ local($_) = $key; $$self[2](); $key = $_; } if($$self[3]){ local($_) = $val; $$self[3](); $val = $_; } my($rv) = plcrput($curia, $key, length($key), $val, length($val), $dmode); $errmsg = plcrerrmsg(); return $rv; } ## # $bool = $curia->out($key); # Method: Delete a record. # `$key' specifies a key. If it is undef, this method has no effect. # If successful, the return value is true, else, it is false. False is returned when no # record corresponds to the specified key. # sub out { my($self) = shift; ($$self[1]) || return FALSE; my($key) = shift; (scalar(@_) == 0) || return FALSE; (defined($key)) || return FALSE; my($curia) = $handles{$$self[0]}; if($$self[2]){ local($_) = $key; $$self[2](); $key = $_; } my($rv) = plcrout($curia, $key, length($key)); $errmsg = plcrerrmsg(); return $rv; } ## # $str = $curia->get($key, $start, $max); # Method: Retrieve a record. # `$key' specifies a key. If it is undef, this method has no effect. # `$start' specifies the offset address of the beginning of the region of the value to be read. # If it is negative or undef, the offset is specified as 0. # `$max' specifies the max size to be read. If it is negative or undef, the size to read is # unlimited. # If successful, the return value is a scalar of the value of the corresponding record, else, it # is undef. undef is returned when no record corresponds to the specified key or the size of # the value of the corresponding record is less than `$start'. # sub get { my($self) = shift; ($$self[1]) || return undef; my($key) = shift; my($start) = shift; my($max) = shift; (scalar(@_) == 0) || return undef; (defined($key)) || return undef; (defined($start) && $start >= 0) || ($start = 0); (defined($max) && $start >= 0) || ($max = -1); my($curia) = $handles{$$self[0]}; if($$self[2]){ local($_) = $key; $$self[2](); $key = $_; } my($rv) = plcrget($curia, $key, length($key), $start, $max); $errmsg = plcrerrmsg(); if($rv && $$self[5]){ local($_) = $rv; $$self[5](); $rv = $_; } return $rv; } ## # $num = $curia->vsiz($key); # Method: Get the size of the value of a record. # `$key' specifies a key. If it is undef, this method has no effect. # If successful, the return value is the size of the value of the corresponding record, else, # it is -1. # Because this method does not read the entity of a record, it is faster than `get'. # sub vsiz { my($self) = shift; ($$self[1]) || return -1; my($key) = shift; (scalar(@_) == 0) || return -1; (defined($key)) || return -1; my($curia) = $handles{$$self[0]}; if($$self[2]){ local($_) = $key; $$self[2](); $key = $_; } my($rv) = plcrvsiz($curia, $key, length($key)); $errmsg = plcrerrmsg(); return $rv; } ## # $bool = $curia->iterinit(); # Method: Initialize the iterator of the database handle. # If successful, the return value is true, else, it is false. # The iterator is used in order to access the key of every record stored in a database. # sub iterinit { my($self) = shift; ($$self[1]) || return FALSE; (scalar(@_) == 0) || return FALSE; my($curia) = $handles{$$self[0]}; my($rv) = plcriterinit($curia); $errmsg = plcrerrmsg(); return $rv; } ## # $str = $curia->iternext(); # Method: Get the next key of the iterator. # If successful, the return value is a scalar of the value of the next key, else, it is undef. # undef is returned when no record is to be get out of the iterator. # It is possible to access every record by iteration of calling this method. However, it is # not assured if updating the database is occurred while the iteration. Besides, the order of # this traversal access method is arbitrary, so it is not assured that the order of storing # matches the one of the traversal access. # sub iternext { my($self) = shift; ($$self[1]) || return undef; (scalar(@_) == 0) || return undef; my($curia) = $handles{$$self[0]}; my($rv) = plcriternext($curia); $errmsg = plcrerrmsg(); if($rv && $$self[4]){ local($_) = $rv; $$self[4](); $rv = $_; } return $rv; } ## # $bool = $curia->setalign($align); # Method: Set alignment of the database handle. # `$align' specifies the basic size of alignment. If it is undef, alignment is cleared. # If successful, the return value is true, else, it is false. # If alignment is set to a database, the efficiency of overwriting values is improved. # The size of alignment is suggested to be average size of the values of the records to be # stored. If alignment is positive, padding whose size is multiple number of the alignment # is placed. If alignment is negative, as `vsiz' is the size of a value, the size of padding # is calculated with `(vsiz / pow(2, abs(align) - 1))'. Because alignment setting is not # saved in a database, you should specify alignment every opening a database. # sub setalign { my($self) = shift; ($$self[1]) || return FALSE; my($align) = shift; (defined($align)) || ($align = 0); (scalar(@_) == 0) || return FALSE; my($curia) = $handles{$$self[0]}; my($rv) = plcrsetalign($curia, $align); $errmsg = plcrerrmsg(); return $rv; } ## # $bool = $curia->setfbpsiz($size); # Method: Set the size of the free block pool. # `$size' specifies the size of the free block pool. If it is undef, the free block pool is not # used. # If successful, the return value is true, else, it is false. # The default size of the free block pool is 16. If the size is greater, the space efficiency of # overwriting values is improved with the time efficiency sacrificed. # sub setfbpsiz { my($self) = shift; ($$self[1]) || return FALSE; my($size) = shift; (defined($size)) || ($size = 0); (scalar(@_) == 0) || return FALSE; my($curia) = $handles{$$self[0]}; my($rv) = plcrsetfbpsiz($curia, $size); $errmsg = plcrerrmsg(); return $rv; } ## # $bool = $curia->sync(); # Method: Synchronize updating contents with the files and the devices. # If successful, the return value is true, else, it is false. # This method is useful when another process uses the connected database directory. # sub sync { my($self) = shift; ($$self[1]) || return FALSE; (scalar(@_) == 0) || return FALSE; my($curia) = $handles{$$self[0]}; my($rv) = plcrsync($curia); $errmsg = plcrerrmsg(); return $rv; } ## # $bool = $curia->optimize($bnum); # Method: Optimize the database. # `$bnum' specifies the number of the elements of the bucket array. If it is undef or not more # than 0, the default value is specified. # If successful, the return value is true, else, it is false. # In an alternating succession of deleting and storing with overwrite or concatenate, # dispensable regions accumulate. This method is useful to do away with them. # sub optimize { my($self) = shift; ($$self[1]) || return FALSE; my($bnum) = shift; (defined($bnum)) || ($bnum = -1); (scalar(@_) == 0) || return FALSE; my($curia) = $handles{$$self[0]}; my($rv) = plcroptimize($curia, $bnum); $errmsg = plcrerrmsg(); return $rv; } ## # $num = $curia->fsiz(); # Method: Get the total size of the database files. # If successful, the return value is the total size of the database files, else, it is -1. # If the total size is more than 2GB, the return value overflows. # sub fsiz { my($self) = shift; ($$self[1]) || return -1; (scalar(@_) == 0) || return -1; my($curia) = $handles{$$self[0]}; my($rv) = plcrfsiz($curia); $errmsg = plcrerrmsg(); return $rv; } ## # $num = $curia->bnum(); # Method: Get the total number of the elements of each bucket array. # If successful, the return value is the total number of the elements of each bucket array, # else, it is -1. # sub bnum { my($self) = shift; ($$self[1]) || return -1; (scalar(@_) == 0) || return -1; my($curia) = $handles{$$self[0]}; my($rv) = plcrbnum($curia); $errmsg = plcrerrmsg(); return $rv; } ## # $num = $curia->rnum(); # Method: Get the number of the records stored in the database. # If successful, the return value is the number of the records stored in the database, else, # it is -1. # sub rnum { my($self) = shift; ($$self[1]) || return -1; (scalar(@_) == 0) || return -1; my($curia) = $handles{$$self[0]}; my($rv) = plcrrnum($curia); $errmsg = plcrerrmsg(); return $rv; } ## # $bool = $curia->writable(); # Method: Check whether the database handle is a writer or not. # The return value is true if the handle is a writer, false if not. # sub writable { my($self) = shift; ($$self[1]) || return FALSE; (scalar(@_) == 0) || return FALSE; my($curia) = $handles{$$self[0]}; my($rv) = plcrwritable($curia); $errmsg = plcrerrmsg(); return $rv; } ## # $bool = $curia->fatalerror(); # Method: Check whether the database has a fatal error or not. # The return value is true if the database has a fatal error, false if not. # sub fatalerror { my($self) = shift; ($$self[1]) || return FALSE; (scalar(@_) == 0) || return FALSE; my($curia) = $handles{$$self[0]}; my($rv) = plcrfatalerror($curia); $errmsg = plcrerrmsg(); return $rv; } ## #: Called automatically by the garbage collector. # Destructor: DESTROY: Release the resources. # If the database handle is not closed yet, it is closed. # sub DESTROY { my($self) = shift; $self->close(); } ## # $curia = tie(%hash, "Curia", $name, $omode, $bnum, $dnum); # Tying Function: TIEHASH: Get the database handle. # sub TIEHASH { my($class, $name, $omode, $bnum, $dnum) = @_; (defined($name)) || return undef; (defined($omode)) || ($omode = OWRITER | OCREAT); (defined($bnum)) || ($bnum = -1); (defined($dnum)) || ($dnum = -1); return $class->new($name, $omode, $bnum, $dnum); } ## # $bool = ($hash{$key} = $val); # Tying Function: STORE: Store a record with overwrite. # sub STORE { my($self, $key, $val) = @_; ($$self[1]) || return FALSE; (defined($key) && defined($val)) || return FALSE; my($curia) = $handles{$$self[0]}; if($$self[2]){ local($_) = $key; $$self[2](); $key = $_; } if($$self[3]){ local($_) = $val; $$self[3](); $val = $_; } my($rv) = plcrput($curia, $key, length($key), $val, length($val), DOVER); ($rv == 0) && ($errmsg = plcrerrmsg()); return $rv; } ## # $bool = delete($hash{$key}); # Tying Function: DELETE: Delete a record. # sub DELETE { my($self, $key) = @_; ($$self[1]) || return FALSE; (defined($key)) || return FALSE; my($curia) = $handles{$$self[0]}; if($$self[2]){ local($_) = $key; $$self[2](); $key = $_; } my($rv) = plcrout($curia, $key, length($key)); $errmsg = plcrerrmsg(); return $rv; } ## # $bool = (%hash = ()); # Tying Function: CLEAR: Delete all records. # sub CLEAR { my($self) = shift; ($self->iterinit()) || return FALSE; my($key); while(defined($key = $self->iternext())){ ($self->out($key)) || return FALSE; } return TRUE; } ## # $str = $hash{$key}; # Tying Function: FETCH: Retrieve whole value of a record. # sub FETCH { my($self, $key) = @_; ($$self[1]) || return undef; (defined($key)) || return undef; my($curia) = $handles{$$self[0]}; if($$self[2]){ local($_) = $key; $$self[2](); $key = $_; } my($rv) = plcrget($curia, $key, length($key), 0, -1); $errmsg = plcrerrmsg(); if($rv && $$self[5]){ local($_) = $rv; $$self[5](); $rv = $_; } return $rv; } ## # $bool = exists($hash{$val}); # Tying Function: EXISTS: Check whether a record exists or not. # sub EXISTS { my($self) = shift; my($key) = shift; return $self->vsiz($key) >= 0 ? TRUE : FALSE; } ## #: Called automatically by keys(), each(), and so on. # Tying Function: FIRSTKEY: Get the first key. # sub FIRSTKEY { my($self) = shift; ($self->iterinit()) || return undef; return $self->iternext(); } ## #: Called automatically by keys(), each(), and so on. # Tying Function: NEXTKEY: Get the next key. # sub NEXTKEY { my($self) = shift; return $self->iternext(); } ## # $func = $curia->filter_store_key(\&nf); # Method: set a filter invoked when writing a key. # `\&nf' specifies the reference of a filter function proofing `$_'. If it is undef, the # current filter function is cleared. # The return value is the old filter function. # sub filter_store_key { my($self) = shift; my($nf) = shift; my($of) = $$self[2]; $$self[2] = $nf; return $of; } ## # $func = $curia->filter_store_value(\&nf); # Method: set a filter invoked when writing a value. # `\&nf' specifies the reference of a filter function proofing `$_'. If it is undef, the # current filter function is cleared. # The return value is the old filter function. # sub filter_store_value { my($self) = shift; my($nf) = shift; my($of) = $$self[3]; $$self[3] = $nf; return $of; } ## # $func = $curia->filter_fetch_key(\&nf); # Method: set a filter invoked when reading a key. # `\&nf' specifies the reference of a filter function proofing `$_'. If it is undef, the # current filter function is cleared. # The return value is the old filter function. # sub filter_fetch_key { my($self) = shift; my($nf) = shift; my($of) = $$self[4]; $$self[4] = $nf; return $of; } ## # $func = $curia->filter_fetch_value(\&nf); # Method: set a filter invoked when reading a value. # `\&nf' specifies the reference a filter function proofing `$_'. If it is undef, the # current filter function is cleared. # The return value is the old filter function. # sub filter_fetch_value { my($self) = shift; my($nf) = shift; my($of) = $$self[5]; $$self[5] = $nf; return $of; } TRUE; # return success code # END OF FILE qdbm-1.8.78/perl/curia/plcrtest0000755000175000017500000002041610445202056015400 0ustar mikiomikio#! /usr/bin/perl -w #================================================================================================= # Test cases of Curia for Perl # Copyright (C) 2000-2005 Mikio Hirabayashi # This file is part of QDBM, Quick Database Manager. # QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU # Lesser General Public License as published by the Free Software Foundation; either version # 2.1 of the License or any later version. QDBM is distributed in the hope that it will be # useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more # details. # You should have received a copy of the GNU Lesser General Public License along with QDBM; if # not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA # 02111-1307 USA. #================================================================================================= use strict; use warnings; use ExtUtils::testlib; use Curia; # main routine sub main { my($rv); (scalar(@ARGV) >= 1) || usage(); if($ARGV[0] eq "write"){ $rv = runwrite(); } elsif($ARGV[0] eq "read"){ $rv = runread(); } elsif($ARGV[0] eq "tie"){ $rv = runtie(); } else { usage(); } return $rv; } # print the usage and exit sub usage { printf(STDERR "$0: test cases for Curia for Perl\n"); printf(STDERR "\n"); printf(STDERR "usage:\n"); printf(STDERR " $0 write name rnum bnum dnum\n"); printf(STDERR " $0 read name\n"); printf(STDERR " $0 tie name\n"); printf(STDERR "\n"); exit(1); } # parse arguments of write command sub runwrite { my($name, $rnum, $bnum, $dnum, $i, $rv); for($i = 1; $i < scalar(@ARGV); $i++){ if(!defined($name) && $ARGV[$i] =~ m/^-/){ usage(); } elsif(!defined($name)){ $name = $ARGV[$i]; } elsif(!defined($rnum)){ $rnum = $ARGV[$i]; } elsif(!defined($bnum)){ $bnum = $ARGV[$i]; } elsif(!defined($dnum)){ $dnum = $ARGV[$i]; } else { usage(); } } (defined($name) && defined($rnum) && defined($bnum) && defined($dnum)) || usage(); ($name && $rnum > 0 && $bnum > 0 && $dnum > 0) || usage(); $rv = dowrite($name, $rnum, $bnum, $dnum); return $rv; } # parse arguments of read command sub runread { my($name, $i, $rv); for($i = 1; $i < scalar(@ARGV); $i++){ if(!defined($name) && $ARGV[$i] =~ m/^-/){ usage(); } elsif(!defined($name)){ $name = $ARGV[$i]; } else { usage(); } } (defined($name)) || usage(); ($name) || usage(); $rv = doread($name); return $rv; } # parse arguments of tie command sub runtie { my($name, $i, $rv); for($i = 1; $i < scalar(@ARGV); $i++){ if(!defined($name) && $ARGV[$i] =~ m/^-/){ usage(); } elsif(!defined($name)){ $name = $ARGV[$i]; } else { usage(); } } (defined($name)) || usage(); ($name) || usage(); $rv = dotie($name); return $rv; } # perform write command sub dowrite { my($name, $rnum, $bnum, $dnum) = @_; my($i, $curia, $buf, $err); printf("\n name=$name rnum=$rnum bnum=$bnum\n\n"); # open a database if(!($curia = new Curia($name, Curia::OWRITER | Curia::OCREAT | Curia::OTRUNC, $bnum, $dnum))){ printf(STDERR "$0: $name: open error: $Curia::errmsg\n"); return 1; } # loop for each record $err = 0; $| = 1; for($i = 1; $i <= $rnum; $i++){ $buf = sprintf("%08d", $i); # store a record if(!$curia->put($buf, $buf, Curia::DKEEP)){ printf(STDERR "$0: $name: put error: $Curia::errmsg\n"); $err = 1; last; } # print progression if($rnum > 250 && $i % ($rnum / 250) == 0){ print('.'); if($i == $rnum || $i % ($rnum / 10) == 0){ printf(" (%08d)\n", $i); } } } # close the database if(!$curia->close()){ printf(STDERR "$0: $name: close error: $Curia::errmsg\n"); return 1; } ($err) || printf("ok\n\n"); return $err ? 1 : 0; } # perform read command sub doread { my($name) = @_; my($i, $curia, $rnum, $buf, $err); printf("\n name=$name\n\n"); # open a database if(!($curia = new Curia($name))){ printf(STDERR "$0: $name: open error: $Curia::errmsg\n"); return 1; } # get the number of records $rnum = $curia->rnum(); # loop for each record $err = 0; $| = 1; for($i = 1; $i <= $rnum; $i++){ $buf = sprintf("%08d", $i); # store a record if(!$curia->get($buf)){ printf(STDERR "$0: $name: get error: $Curia::errmsg\n"); $err = 1; last; } # print progression if($rnum > 250 && $i % ($rnum / 250) == 0){ print('.'); if($i == $rnum || $i % ($rnum / 10) == 0){ printf(" (%08d)\n", $i); } } } # close the database if(!$curia->close()){ printf(STDERR "$0: $name: close error: $Curia::errmsg\n"); return 1; } ($err) || printf("ok\n\n"); return $err ? 1 : 0; } # perform tie command sub dotie { my($name) = @_; my($LOOPNUM) = 100; my($BUCKETNUM) = 16; my($DIVNUM) = 3; my($i, $curia, $rnum, %hash, $buf, $key, $val); printf("\n name=$name\n\n"); $| = 1; # open the database printf("Creating a database with tied hash ... "); if(!($curia = tie(%hash, "Curia", $name, Curia::OWRITER | Curia::OCREAT | Curia::OTRUNC, $BUCKETNUM, $DIVNUM))){ printf(STDERR "$0: $name: open error: $Curia::errmsg\n"); return 1; } printf("ok\n"); # store records printf("Storing records into tied hash ... "); for($i = 1; $i <= $LOOPNUM; $i++){ $buf = sprintf("%08d", $i); if(!($hash{$buf} = $buf)){ printf(STDERR "$0: $name: store error: $Curia::errmsg\n"); return 1; } } printf("ok\n"); # retrieve records printf("Retrieving records in tied hash ... "); for($i = 1; $i <= $LOOPNUM; $i++){ $buf = sprintf("%08d", $i); if(!$hash{$buf}){ printf(STDERR "$0: $name: fetch error: $Curia::errmsg\n"); return 1; } } printf("ok\n"); # traverse records printf("Traversing records in tied hash ... "); $i = 0; while(($key, $val) = each(%hash)){ if($key ne $val){ printf(STDERR "$0: $name: each error: $Curia::errmsg\n"); return 1; } $i++; } if($i != $LOOPNUM){ printf(STDERR "$0: $name: each error: $Curia::errmsg\n"); return 1; } printf("ok\n"); # delete a record printf("Deleting a record in tied hash ... "); $buf = sprintf("%08d", $LOOPNUM / 2); if(!(delete $hash{$buf}) || scalar(keys(%hash)) != $LOOPNUM - 1){ printf(STDERR "$0: $name: delete error: $Curia::errmsg\n"); return 1; } printf("ok\n"); # clear the hash printf("Clear a record in tied hash ... "); %hash = (); if(scalar(keys(%hash)) != 0){ printf(STDERR "$0: $name: clear error: $Curia::errmsg\n"); return 1; } printf("ok\n"); # test filters printf("Testing filters ... "); $curia->filter_store_key(sub { s/$/\0/; }); $curia->filter_store_value(sub { s/$/\0/; }); $curia->filter_fetch_key(sub { s/\0$//; }); $curia->filter_fetch_value(sub { s/\0$//; }); $hash{"tako"} = "ika"; if(!exists($hash{"tako"}) || scalar(keys(%hash)) != 1 || scalar(values(%hash)) != 1 || $hash{"tako"} ne "ika" || !delete($hash{"tako"})){ printf(STDERR "$0: $name: filter error: $Curia::errmsg\n"); return 1; } printf("ok\n"); # close the database printf("Closing the tied hash ... "); $curia = undef; untie(%hash); printf("ok\n"); printf("all ok\n\n"); return 0; } # execute main $0 =~ s/.*\///; exit(main()); # END OF FILE qdbm-1.8.78/perl/curia/Makefile.PL0000644000175000017500000000055107657162102015572 0ustar mikiomikio#================================================================================================= # Script for MakeMaker #================================================================================================= use ExtUtils::MakeMaker; # Create Makefile WriteMakefile( 'NAME' => 'Curia', 'VERSION_FROM' => 'Curia.pm', ); # END OF FILE qdbm-1.8.78/perl/curia/Curia.xs0000644000175000017500000000714510443772625015251 0ustar mikiomikio/************************************************************************************************* * Curia.c * Copyright (C) 2000-2005 Mikio Hirabayashi * This file is part of QDBM, Quick Database Manager. * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU * Lesser General Public License as published by the Free Software Foundation; either version * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * You should have received a copy of the GNU Lesser General Public License along with QDBM; if * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. *************************************************************************************************/ #include "EXTERN.h" #include "perl.h" #include "XSUB.h" #include #include #include MODULE = Curia PACKAGE = Curia PROTOTYPES: DISABLE ##================================================================================================ ## public objects ##================================================================================================ const char * plcrerrmsg() CODE: RETVAL = dperrmsg(dpecode); OUTPUT: RETVAL void * plcropen(name, omode, bnum, dnum) char * name int omode int bnum int dnum CODE: RETVAL = cropen(name, omode, bnum, dnum); OUTPUT: RETVAL int plcrclose(curia) void *curia CODE: RETVAL = crclose(curia); OUTPUT: RETVAL int plcrput(curia, kbuf, ksiz, vbuf, vsiz, dmode) void * curia char * kbuf int ksiz char * vbuf int vsiz int dmode CODE: RETVAL = crput(curia, kbuf, ksiz, vbuf, vsiz, dmode); OUTPUT: RETVAL int plcrout(curia, kbuf, ksiz) void * curia char * kbuf int ksiz CODE: RETVAL = crout(curia, kbuf, ksiz); OUTPUT: RETVAL void plcrget(curia, kbuf, ksiz, start, max) void * curia char * kbuf int ksiz int start int max PREINIT: char *vbuf; int vsiz; PPCODE: vbuf = crget(curia, kbuf, ksiz, start, max, &vsiz); if(!vbuf) XSRETURN_UNDEF; XPUSHs(sv_2mortal(newSVpv(vbuf, vsiz))); free(vbuf); XSRETURN(1); int plcrvsiz(curia, kbuf, ksiz) void * curia char * kbuf int ksiz CODE: RETVAL = crvsiz(curia, kbuf, ksiz); OUTPUT: RETVAL int plcriterinit(curia) void * curia CODE: RETVAL = criterinit(curia); OUTPUT: RETVAL void plcriternext(curia) void * curia PREINIT: char *kbuf; int ksiz; PPCODE: kbuf = criternext(curia, &ksiz); if(!kbuf) XSRETURN_UNDEF; XPUSHs(sv_2mortal(newSVpv(kbuf, ksiz))); free(kbuf); XSRETURN(1); int plcrsetalign(curia, align) void * curia int align CODE: RETVAL = crsetalign(curia, align); OUTPUT: RETVAL int plcrsetfbpsiz(curia, size) void * curia int size CODE: RETVAL = crsetfbpsiz(curia, size); OUTPUT: RETVAL int plcrsync(curia) void * curia CODE: RETVAL = crsync(curia); OUTPUT: RETVAL int plcroptimize(curia, bnum) void * curia int bnum CODE: RETVAL = croptimize(curia, bnum); OUTPUT: RETVAL int plcrfsiz(curia) void * curia CODE: RETVAL = crfsiz(curia); OUTPUT: RETVAL int plcrbnum(curia) void * curia CODE: RETVAL = crbnum(curia); OUTPUT: RETVAL int plcrrnum(curia) void * curia CODE: RETVAL = crrnum(curia); OUTPUT: RETVAL int plcrwritable(curia) void * curia CODE: RETVAL = crwritable(curia); OUTPUT: RETVAL int plcrfatalerror(curia) void * curia CODE: RETVAL = crfatalerror(curia); OUTPUT: RETVAL ## END OF FILE qdbm-1.8.78/perl/depot/0000755000175000017500000000000010705266453013631 5ustar mikiomikioqdbm-1.8.78/perl/depot/MANIFEST0000644000175000017500000000006007727054331014756 0ustar mikiomikioMANIFEST Makefile.PL Depot.pm Depot.xs pldptest qdbm-1.8.78/perl/depot/Makefile.PL0000644000175000017500000000055107657161452015611 0ustar mikiomikio#================================================================================================= # Script for MakeMaker #================================================================================================= use ExtUtils::MakeMaker; # Create Makefile WriteMakefile( 'NAME' => 'Depot', 'VERSION_FROM' => 'Depot.pm', ); # END OF FILE qdbm-1.8.78/perl/depot/Depot.pm0000644000175000017500000004777410445176466015272 0ustar mikiomikio#================================================================================================= # Perl API of Depot, the basic API of QDBM # Copyright (C) 2000-2005 Mikio Hirabayashi # This file is part of QDBM, Quick Database Manager. # QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU # Lesser General Public License as published by the Free Software Foundation; either version # 2.1 of the License or any later version. QDBM is distributed in the hope that it will be # useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more # details. # You should have received a copy of the GNU Lesser General Public License along with QDBM; if # not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA # 02111-1307 USA. #================================================================================================= package Depot; use strict; use warnings; require Tie::Hash; require Exporter; require XSLoader; our @ISA = qw(Tie::Hash Exporter); our $VERSION = '1.0'; XSLoader::load('Depot', $VERSION); use constant TRUE => 1; # boolean true use constant FALSE => 0; # boolean false use constant OREADER => 1 << 0; # open as a reader use constant OWRITER => 1 << 1; # open as a writer use constant OCREAT => 1 << 2; # a writer creating use constant OTRUNC => 1 << 3; # a writer truncating use constant ONOLCK => 1 << 4; # open without locking use constant OLCKNB => 1 << 5; # lock without blocking use constant OSPARSE => 1 << 6; # create as a sparse file use constant DOVER => 0; # overwrite an existing value use constant DKEEP => 1; # keep an existing value use constant DCAT => 2; # concatenate values my(%handles) = (); # table of database names our($errmsg) = "no error"; # message of the last error #================================================================================================= # public objects #================================================================================================= ## # use Depot; # Module `Depot' should be loaded in application codes. # An instance of the class `Depot' is used as a database handle. # ## # $Depot::errmsg; # Global Variable: The message of the last happened error. # ## # $depot = new Depot($name, $omode, $bnum); # Constructor: Get the database handle. # `$name' specifies the name of a database file. # `$omode' specifies the connection mode: `Depot::OWRITER' as a writer, `Depot::OREADER' as a # reader. If the mode is `Depot::OWRITER', the following may be added by bitwise or: # `Depot::OCREAT', which means it creates a new database if not exist, `Depot::OTRUNC', which # means it creates a new database regardless if one exists. Both of `Depot::OREADER' and # `Depot::OWRITER' can be added to by bitwise or: `Depot::ONOLCK', which means it opens a # database file without file locking, or `Depot::OLCKNB', which means locking is performed # without blocking. `Depot::OCREAT' can be added to by bitwise or: `Depot::OSPARSE', which means # it creates a database file as a sparse file. If it is undef, `Depot::OREADER' is specified. # `$bnum' specifies the number of elements of the bucket array. If it is undef or not more # than 0, the default value is specified. The size of a bucket array is determined on creating, # and can not be changed except for by optimization of the database. Suggested size of a # bucket array is about from 0.5 to 4 times of the number of all records to store. # The return value is the database handle or undef if it is not successful. # While connecting as a writer, an exclusive lock is invoked to the database file. # While connecting as a reader, a shared lock is invoked to the database file. The thread # blocks until the lock is achieved. If `Depot::ONOLCK' is used, the application is responsible # for exclusion control. # sub new { my($class) = shift; my($name) = shift; my($omode) = shift; my($bnum) = shift; (defined($name) && length($name) > 0 && scalar(@_) == 0) || return undef; (!$handles{$name}) || return undef; (defined($omode)) || ($omode = OREADER); (defined($bnum)) || ($bnum = -1); my($depot) = pldpopen($name, $omode, $bnum); $errmsg = pldperrmsg(); ($depot > 0) || return undef; $handles{$name} = $depot; my $self = [$name, TRUE, undef, undef, undef, undef]; bless($self, $class); return $self; } ## # $bool = $depot->close(); # Method: Close the database handle. # If successful, the return value is true, else, it is false. # Because the region of a closed handle is released, it becomes impossible to use the handle. # Updating a database is assured to be written when the handle is closed. If a writer opens # a database but does not close it appropriately, the database will be broken. # sub close { my($self) = shift; ($$self[1]) || return FALSE; (scalar(@_) == 0) || return FALSE; $$self[1] = FALSE; my($depot) = $handles{$$self[0]}; my($rv) = pldpclose($depot); $errmsg = pldperrmsg(); delete($handles{$$self[0]}); return $rv; } ## # $bool = $depot->put($key, $val, $dmode); # Method: Store a record. # `$key' specifies a key. If it is undef, this method has no effect. # `$val' specifies a value. If it is undef, this method has no effect. # `$dmode' specifies behavior when the key overlaps, by the following values: `Depot::DOVER', # which means the specified value overwrites the existing one, `Depot::DKEEP', which means the # existing value is kept, `Depot::DCAT', which means the specified value is concatenated at # the end of the existing value. If it is undef, `Depot::DOVER' is specified. # If successful, the return value is true, else, it is false. # sub put { my($self) = shift; ($$self[1]) || return FALSE; my($key) = shift; my($val) = shift; my($dmode) = shift; (scalar(@_) == 0) || return FALSE; (defined($key) && defined($val)) || return FALSE; (defined($dmode)) || ($dmode = DOVER); my($depot) = $handles{$$self[0]}; if($$self[2]){ local($_) = $key; $$self[2](); $key = $_; } if($$self[3]){ local($_) = $val; $$self[3](); $val = $_; } my($rv) = pldpput($depot, $key, length($key), $val, length($val), $dmode); $errmsg = pldperrmsg(); return $rv; } ## # $bool = $depot->out($key); # Method: Delete a record. # `$key' specifies a key. If it is undef, this method has no effect. # If successful, the return value is true, else, it is false. False is returned when no # record corresponds to the specified key. # sub out { my($self) = shift; ($$self[1]) || return FALSE; my($key) = shift; (scalar(@_) == 0) || return FALSE; (defined($key)) || return FALSE; my($depot) = $handles{$$self[0]}; if($$self[2]){ local($_) = $key; $$self[2](); $key = $_; } my($rv) = pldpout($depot, $key, length($key)); $errmsg = pldperrmsg(); return $rv; } ## # $str = $depot->get($key, $start, $max); # Method: Retrieve a record. # `$key' specifies a key. If it is undef, this method has no effect. # `$start' specifies the offset address of the beginning of the region of the value to be read. # If it is negative or undef, the offset is specified as 0. # `$max' specifies the max size to be read. If it is negative or undef, the size to read is # unlimited. # If successful, the return value is a scalar of the value of the corresponding record, else, it # is undef. undef is returned when no record corresponds to the specified key or the size of # the value of the corresponding record is less than `$start'. # sub get { my($self) = shift; ($$self[1]) || return undef; my($key) = shift; my($start) = shift; my($max) = shift; (scalar(@_) == 0) || return undef; (defined($key)) || return undef; (defined($start) && $start >= 0) || ($start = 0); (defined($max) && $start >= 0) || ($max = -1); my($depot) = $handles{$$self[0]}; if($$self[2]){ local($_) = $key; $$self[2](); $key = $_; } my($rv) = pldpget($depot, $key, length($key), $start, $max); $errmsg = pldperrmsg(); if($rv && $$self[5]){ local($_) = $rv; $$self[5](); $rv = $_; } return $rv; } ## # $num = $depot->vsiz($key); # Method: Get the size of the value of a record. # `$key' specifies a key. If it is undef, this method has no effect. # If successful, the return value is the size of the value of the corresponding record, else, # it is -1. # Because this method does not read the entity of a record, it is faster than `get'. # sub vsiz { my($self) = shift; ($$self[1]) || return -1; my($key) = shift; (scalar(@_) == 0) || return -1; (defined($key)) || return -1; my($depot) = $handles{$$self[0]}; if($$self[2]){ local($_) = $key; $$self[2](); $key = $_; } my($rv) = pldpvsiz($depot, $key, length($key)); $errmsg = pldperrmsg(); return $rv; } ## # $bool = $depot->iterinit(); # Method: Initialize the iterator of the database handle. # If successful, the return value is true, else, it is false. # The iterator is used in order to access the key of every record stored in a database. # sub iterinit { my($self) = shift; ($$self[1]) || return FALSE; (scalar(@_) == 0) || return FALSE; my($depot) = $handles{$$self[0]}; my($rv) = pldpiterinit($depot); $errmsg = pldperrmsg(); return $rv; } ## # $str = $depot->iternext(); # Method: Get the next key of the iterator. # If successful, the return value is a scalar of the value of the next key, else, it is undef. # undef is returned when no record is to be get out of the iterator. # It is possible to access every record by iteration of calling this method. However, it is # not assured if updating the database is occurred while the iteration. Besides, the order of # this traversal access method is arbitrary, so it is not assured that the order of storing # matches the one of the traversal access. # sub iternext { my($self) = shift; ($$self[1]) || return undef; (scalar(@_) == 0) || return undef; my($depot) = $handles{$$self[0]}; my($rv) = pldpiternext($depot); $errmsg = pldperrmsg(); if($rv && $$self[4]){ local($_) = $rv; $$self[4](); $rv = $_; } return $rv; } ## # $bool = $depot->setalign($align); # Method: Set alignment of the database handle. # `$align' specifies the basic size of alignment. If it is undef, alignment is cleared. # If successful, the return value is true, else, it is false. # If alignment is set to a database, the efficiency of overwriting values is improved. # The size of alignment is suggested to be average size of the values of the records to be # stored. If alignment is positive, padding whose size is multiple number of the alignment # is placed. If alignment is negative, as `vsiz' is the size of a value, the size of padding # is calculated with `(vsiz / pow(2, abs(align) - 1))'. Because alignment setting is not # saved in a database, you should specify alignment every opening a database. # sub setalign { my($self) = shift; ($$self[1]) || return FALSE; my($align) = shift; (defined($align)) || ($align = 0); (scalar(@_) == 0) || return FALSE; my($depot) = $handles{$$self[0]}; my($rv) = pldpsetalign($depot, $align); $errmsg = pldperrmsg(); return $rv; } ## # $bool = $depot->setfbpsiz($size); # Method: Set the size of the free block pool. # `$size' specifies the size of the free block pool. If it is undef, the free block pool is not # used. # If successful, the return value is true, else, it is false. # The default size of the free block pool is 16. If the size is greater, the space efficiency of # overwriting values is improved with the time efficiency sacrificed. # sub setfbpsiz { my($self) = shift; ($$self[1]) || return FALSE; my($size) = shift; (defined($size)) || ($size = 0); (scalar(@_) == 0) || return FALSE; my($depot) = $handles{$$self[0]}; my($rv) = pldpsetfbpsiz($depot, $size); $errmsg = pldperrmsg(); return $rv; } ## # $bool = $depot->sync(); # Method: Synchronize updating contents with the file and the device. # If successful, the return value is true, else, it is false. # This method is useful when another process uses the connected database file. # sub sync { my($self) = shift; ($$self[1]) || return FALSE; (scalar(@_) == 0) || return FALSE; my($depot) = $handles{$$self[0]}; my($rv) = pldpsync($depot); $errmsg = pldperrmsg(); return $rv; } ## # $bool = $depot->optimize($bnum); # Method: Optimize the database. # `$bnum' specifies the number of the elements of the bucket array. If it is undef or not more # than 0, the default value is specified. # If successful, the return value is true, else, it is false. # In an alternating succession of deleting and storing with overwrite or concatenate, # dispensable regions accumulate. This method is useful to do away with them. # sub optimize { my($self) = shift; ($$self[1]) || return FALSE; my($bnum) = shift; (defined($bnum)) || ($bnum = -1); (scalar(@_) == 0) || return FALSE; my($depot) = $handles{$$self[0]}; my($rv) = pldpoptimize($depot, $bnum); $errmsg = pldperrmsg(); return $rv; } ## # $num = $depot->fsiz(); # Method: Get the size of the database file. # If successful, the return value is the size of the database file, else, it is -1. # sub fsiz { my($self) = shift; ($$self[1]) || return -1; (scalar(@_) == 0) || return -1; my($depot) = $handles{$$self[0]}; my($rv) = pldpfsiz($depot); $errmsg = pldperrmsg(); return $rv; } ## # $num = $depot->bnum(); # Method: Get the number of the elements of the bucket array. # If successful, the return value is the number of the elements of the bucket array, else, it # is -1. # sub bnum { my($self) = shift; ($$self[1]) || return -1; (scalar(@_) == 0) || return -1; my($depot) = $handles{$$self[0]}; my($rv) = pldpbnum($depot); $errmsg = pldperrmsg(); return $rv; } ## # $num = $depot->rnum(); # Method: Get the number of the records stored in the database. # If successful, the return value is the number of the records stored in the database, else, # it is -1. # sub rnum { my($self) = shift; ($$self[1]) || return -1; (scalar(@_) == 0) || return -1; my($depot) = $handles{$$self[0]}; my($rv) = pldprnum($depot); $errmsg = pldperrmsg(); return $rv; } ## # $bool = $depot->writable(); # Method: Check whether the database handle is a writer or not. # The return value is true if the handle is a writer, false if not. # sub writable { my($self) = shift; ($$self[1]) || return FALSE; (scalar(@_) == 0) || return FALSE; my($depot) = $handles{$$self[0]}; my($rv) = pldpwritable($depot); $errmsg = pldperrmsg(); return $rv; } ## # $bool = $depot->fatalerror(); # Method: Check whether the database has a fatal error or not. # The return value is true if the database has a fatal error, false if not. # sub fatalerror { my($self) = shift; ($$self[1]) || return FALSE; (scalar(@_) == 0) || return FALSE; my($depot) = $handles{$$self[0]}; my($rv) = pldpfatalerror($depot); $errmsg = pldperrmsg(); return $rv; } ## #: Called automatically by the garbage collector. # Destructor: DESTROY: Release the resources. # If the database handle is not closed yet, it is closed. # sub DESTROY { my($self) = shift; $self->close(); } ## # $depot = tie(%hash, "Depot", $name, $omode, $bnum); # Tying Function: TIEHASH: Get the database handle. # sub TIEHASH { my($class, $name, $omode, $bnum) = @_; (defined($name)) || return undef; (defined($omode)) || ($omode = OWRITER | OCREAT); (defined($bnum)) || ($bnum = -1); return $class->new($name, $omode, $bnum); } ## # $bool = ($hash{$key} = $val); # Tying Function: STORE: Store a record with overwrite. # sub STORE { my($self, $key, $val) = @_; ($$self[1]) || return FALSE; (defined($key) && defined($val)) || return FALSE; my($depot) = $handles{$$self[0]}; if($$self[2]){ local($_) = $key; $$self[2](); $key = $_; } if($$self[3]){ local($_) = $val; $$self[3](); $val = $_; } my($rv) = pldpput($depot, $key, length($key), $val, length($val), DOVER); ($rv == 0) && ($errmsg = pldperrmsg()); return $rv; } ## # $bool = delete($hash{$key}); # Tying Function: DELETE: Delete a record. # sub DELETE { my($self, $key) = @_; ($$self[1]) || return FALSE; (defined($key)) || return FALSE; my($depot) = $handles{$$self[0]}; if($$self[2]){ local($_) = $key; $$self[2](); $key = $_; } my($rv) = pldpout($depot, $key, length($key)); $errmsg = pldperrmsg(); return $rv; } ## # $bool = (%hash = ()); # Tying Function: CLEAR: Delete all records. # sub CLEAR { my($self) = shift; ($self->iterinit()) || return FALSE; my($key); while(defined($key = $self->iternext())){ ($self->out($key)) || return FALSE; } return TRUE; } ## # $str = $hash{$key}; # Tying Function: FETCH: Retrieve whole value of a record. # sub FETCH { my($self, $key) = @_; ($$self[1]) || return undef; (defined($key)) || return undef; my($depot) = $handles{$$self[0]}; if($$self[2]){ local($_) = $key; $$self[2](); $key = $_; } my($rv) = pldpget($depot, $key, length($key), 0, -1); $errmsg = pldperrmsg(); if($rv && $$self[5]){ local($_) = $rv; $$self[5](); $rv = $_; } return $rv; } ## # $bool = exists($hash{$val}); # Tying Function: EXISTS: Check whether a record exists or not. # sub EXISTS { my($self) = shift; my($key) = shift; return $self->vsiz($key) >= 0 ? TRUE : FALSE; } ## #: Called automatically by keys(), each(), and so on. # Tying Function: FIRSTKEY: Get the first key. # sub FIRSTKEY { my($self) = shift; ($self->iterinit()) || return undef; return $self->iternext(); } ## #: Called automatically by keys(), each(), and so on. # Tying Function: NEXTKEY: Get the next key. # sub NEXTKEY { my($self) = shift; return $self->iternext(); } ## # $func = $depot->filter_store_key(\&nf); # Method: set a filter invoked when writing a key. # `\&nf' specifies the reference of a filter function proofing `$_'. If it is undef, the # current filter function is cleared. # The return value is the old filter function. # sub filter_store_key { my($self) = shift; my($nf) = shift; my($of) = $$self[2]; $$self[2] = $nf; return $of; } ## # $func = $depot->filter_store_value(\&nf); # Method: set a filter invoked when writing a value. # `\&nf' specifies the reference of a filter function proofing `$_'. If it is undef, the # current filter function is cleared. # The return value is the old filter function. # sub filter_store_value { my($self) = shift; my($nf) = shift; my($of) = $$self[3]; $$self[3] = $nf; return $of; } ## # $func = $depot->filter_fetch_key(\&nf); # Method: set a filter invoked when reading a key. # `\&nf' specifies the reference of a filter function proofing `$_'. If it is undef, the # current filter function is cleared. # The return value is the old filter function. # sub filter_fetch_key { my($self) = shift; my($nf) = shift; my($of) = $$self[4]; $$self[4] = $nf; return $of; } ## # $func = $depot->filter_fetch_value(\&nf); # Method: set a filter invoked when reading a value. # `\&nf' specifies the reference of a filter function proofing `$_'. If it is undef, the # current filter function is cleared. # The return value is the old filter function. # sub filter_fetch_value { my($self) = shift; my($nf) = shift; my($of) = $$self[5]; $$self[5] = $nf; return $of; } TRUE; # return success code # END OF FILE qdbm-1.8.78/perl/depot/Depot.xs0000644000175000017500000000707310443772511015263 0ustar mikiomikio/************************************************************************************************* * Depot.c * Copyright (C) 2000-2005 Mikio Hirabayashi * This file is part of QDBM, Quick Database Manager. * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU * Lesser General Public License as published by the Free Software Foundation; either version * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * You should have received a copy of the GNU Lesser General Public License along with QDBM; if * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. *************************************************************************************************/ #include "EXTERN.h" #include "perl.h" #include "XSUB.h" #include #include MODULE = Depot PACKAGE = Depot PROTOTYPES: DISABLE ##================================================================================================ ## public objects ##================================================================================================ const char * pldperrmsg() CODE: RETVAL = dperrmsg(dpecode); OUTPUT: RETVAL void * pldpopen(name, omode, bnum) char * name int omode int bnum CODE: RETVAL = dpopen(name, omode, bnum); OUTPUT: RETVAL int pldpclose(depot) void *depot CODE: RETVAL = dpclose(depot); OUTPUT: RETVAL int pldpput(depot, kbuf, ksiz, vbuf, vsiz, dmode) void * depot char * kbuf int ksiz char * vbuf int vsiz int dmode CODE: RETVAL = dpput(depot, kbuf, ksiz, vbuf, vsiz, dmode); OUTPUT: RETVAL int pldpout(depot, kbuf, ksiz) void * depot char * kbuf int ksiz CODE: RETVAL = dpout(depot, kbuf, ksiz); OUTPUT: RETVAL void pldpget(depot, kbuf, ksiz, start, max) void * depot char * kbuf int ksiz int start int max PREINIT: char *vbuf; int vsiz; PPCODE: vbuf = dpget(depot, kbuf, ksiz, start, max, &vsiz); if(!vbuf) XSRETURN_UNDEF; XPUSHs(sv_2mortal(newSVpv(vbuf, vsiz))); free(vbuf); XSRETURN(1); int pldpvsiz(depot, kbuf, ksiz) void * depot char * kbuf int ksiz CODE: RETVAL = dpvsiz(depot, kbuf, ksiz); OUTPUT: RETVAL int pldpiterinit(depot) void * depot CODE: RETVAL = dpiterinit(depot); OUTPUT: RETVAL void pldpiternext(depot) void * depot PREINIT: char *kbuf; int ksiz; PPCODE: kbuf = dpiternext(depot, &ksiz); if(!kbuf) XSRETURN_UNDEF; XPUSHs(sv_2mortal(newSVpv(kbuf, ksiz))); free(kbuf); XSRETURN(1); int pldpsetalign(depot, align) void * depot int align CODE: RETVAL = dpsetalign(depot, align); OUTPUT: RETVAL int pldpsetfbpsiz(depot, size) void * depot int size CODE: RETVAL = dpsetfbpsiz(depot, size); OUTPUT: RETVAL int pldpsync(depot) void * depot CODE: RETVAL = dpsync(depot); OUTPUT: RETVAL int pldpoptimize(depot, bnum) void * depot int bnum CODE: RETVAL = dpoptimize(depot, bnum); OUTPUT: RETVAL int pldpfsiz(depot) void * depot CODE: RETVAL = dpfsiz(depot); OUTPUT: RETVAL int pldpbnum(depot) void * depot CODE: RETVAL = dpbnum(depot); OUTPUT: RETVAL int pldprnum(depot) void * depot CODE: RETVAL = dprnum(depot); OUTPUT: RETVAL int pldpwritable(depot) void * depot CODE: RETVAL = dpwritable(depot); OUTPUT: RETVAL int pldpfatalerror(depot) void * depot CODE: RETVAL = dpfatalerror(depot); OUTPUT: RETVAL ## END OF FILE qdbm-1.8.78/perl/depot/pldptest0000755000175000017500000002012710445202041015400 0ustar mikiomikio#! /usr/bin/perl -w #================================================================================================= # Test cases of Depot for Perl # Copyright (C) 2000-2005 Mikio Hirabayashi # This file is part of QDBM, Quick Database Manager. # QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU # Lesser General Public License as published by the Free Software Foundation; either version # 2.1 of the License or any later version. QDBM is distributed in the hope that it will be # useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more # details. # You should have received a copy of the GNU Lesser General Public License along with QDBM; if # not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA # 02111-1307 USA. #================================================================================================= use strict; use warnings; use ExtUtils::testlib; use Depot; # main routine sub main { my($rv); (scalar(@ARGV) >= 1) || usage(); if($ARGV[0] eq "write"){ $rv = runwrite(); } elsif($ARGV[0] eq "read"){ $rv = runread(); } elsif($ARGV[0] eq "tie"){ $rv = runtie(); } else { usage(); } return $rv; } # print the usage and exit sub usage { printf(STDERR "$0: test cases for Depot for Perl\n"); printf(STDERR "\n"); printf(STDERR "usage:\n"); printf(STDERR " $0 write name rnum bnum\n"); printf(STDERR " $0 read name\n"); printf(STDERR " $0 tie name\n"); printf(STDERR "\n"); exit(1); } # parse arguments of write command sub runwrite { my($name, $rnum, $bnum, $i, $rv); for($i = 1; $i < scalar(@ARGV); $i++){ if(!defined($name) && $ARGV[$i] =~ m/^-/){ usage(); } elsif(!defined($name)){ $name = $ARGV[$i]; } elsif(!defined($rnum)){ $rnum = $ARGV[$i]; } elsif(!defined($bnum)){ $bnum = $ARGV[$i]; } else { usage(); } } (defined($name) && defined($rnum) && defined($bnum)) || usage(); ($name && $rnum > 0 && $bnum > 0) || usage(); $rv = dowrite($name, $rnum, $bnum); return $rv; } # parse arguments of read command sub runread { my($name, $i, $rv); for($i = 1; $i < scalar(@ARGV); $i++){ if(!defined($name) && $ARGV[$i] =~ m/^-/){ usage(); } elsif(!defined($name)){ $name = $ARGV[$i]; } else { usage(); } } (defined($name)) || usage(); ($name) || usage(); $rv = doread($name); return $rv; } # parse arguments of tie command sub runtie { my($name, $i, $rv); for($i = 1; $i < scalar(@ARGV); $i++){ if(!defined($name) && $ARGV[$i] =~ m/^-/){ usage(); } elsif(!defined($name)){ $name = $ARGV[$i]; } else { usage(); } } (defined($name)) || usage(); ($name) || usage(); $rv = dotie($name); return $rv; } # perform write command sub dowrite { my($name, $rnum, $bnum) = @_; my($i, $depot, $buf, $err); printf("\n name=$name rnum=$rnum bnum=$bnum\n\n"); # open a database if(!($depot = new Depot($name, Depot::OWRITER | Depot::OCREAT | Depot::OTRUNC, $bnum))){ printf(STDERR "$0: $name: open error: $Depot::errmsg\n"); return 1; } # loop for each record $err = 0; $| = 1; for($i = 1; $i <= $rnum; $i++){ $buf = sprintf("%08d", $i); # store a record if(!$depot->put($buf, $buf, Depot::DKEEP)){ printf(STDERR "$0: $name: put error: $Depot::errmsg\n"); $err = 1; last; } # print progression if($rnum > 250 && $i % ($rnum / 250) == 0){ print('.'); if($i == $rnum || $i % ($rnum / 10) == 0){ printf(" (%08d)\n", $i); } } } # close the database if(!$depot->close()){ printf(STDERR "$0: $name: close error: $Depot::errmsg\n"); return 1; } ($err) || printf("ok\n\n"); return $err ? 1 : 0; } # perform read command sub doread { my($name) = @_; my($i, $depot, $rnum, $buf, $err); printf("\n name=$name\n\n"); # open a database if(!($depot = new Depot($name))){ printf(STDERR "$0: $name: open error: $Depot::errmsg\n"); return 1; } # get the number of records $rnum = $depot->rnum(); # loop for each record $err = 0; $| = 1; for($i = 1; $i <= $rnum; $i++){ $buf = sprintf("%08d", $i); # store a record if(!$depot->get($buf)){ printf(STDERR "$0: $name: get error: $Depot::errmsg\n"); $err = 1; last; } # print progression if($rnum > 250 && $i % ($rnum / 250) == 0){ print('.'); if($i == $rnum || $i % ($rnum / 10) == 0){ printf(" (%08d)\n", $i); } } } # close the database if(!$depot->close()){ printf(STDERR "$0: $name: close error: $Depot::errmsg\n"); return 1; } ($err) || printf("ok\n\n"); return $err ? 1 : 0; } # perform tie command sub dotie { my($name) = @_; my($LOOPNUM) = 100; my($BUCKETNUM) = 16; my($i, $depot, $rnum, %hash, $buf, $key, $val); printf("\n name=$name\n\n"); $| = 1; # open the database printf("Creating a database with tied hash ... "); if(!($depot = tie(%hash, "Depot", $name, Depot::OWRITER | Depot::OCREAT | Depot::OTRUNC, $BUCKETNUM))){ printf(STDERR "$0: $name: open error: $Depot::errmsg\n"); return 1; } printf("ok\n"); # store records printf("Storing records into tied hash ... "); for($i = 1; $i <= $LOOPNUM; $i++){ $buf = sprintf("%08d", $i); if(!($hash{$buf} = $buf)){ printf(STDERR "$0: $name: store error: $Depot::errmsg\n"); return 1; } } printf("ok\n"); # retrieve records printf("Retrieving records in tied hash ... "); for($i = 1; $i <= $LOOPNUM; $i++){ $buf = sprintf("%08d", $i); if(!$hash{$buf}){ printf(STDERR "$0: $name: fetch error: $Depot::errmsg\n"); return 1; } } printf("ok\n"); # traverse records printf("Traversing records in tied hash ... "); $i = 0; while(($key, $val) = each(%hash)){ if($key ne $val){ printf(STDERR "$0: $name: each error: $Depot::errmsg\n"); return 1; } $i++; } if($i != $LOOPNUM){ printf(STDERR "$0: $name: each error: $Depot::errmsg\n"); return 1; } printf("ok\n"); # delete a record printf("Deleting a record in tied hash ... "); $buf = sprintf("%08d", $LOOPNUM / 2); if(!(delete $hash{$buf}) || scalar(keys(%hash)) != $LOOPNUM - 1){ printf(STDERR "$0: $name: delete error: $Depot::errmsg\n"); return 1; } printf("ok\n"); # clear the hash printf("Clear a record in tied hash ... "); %hash = (); if(scalar(keys(%hash)) != 0){ printf(STDERR "$0: $name: clear error: $Depot::errmsg\n"); return 1; } printf("ok\n"); # test filters printf("Testing filters ... "); $depot->filter_store_key(sub { s/$/\0/; }); $depot->filter_store_value(sub { s/$/\0/; }); $depot->filter_fetch_key(sub { s/\0$//; }); $depot->filter_fetch_value(sub { s/\0$//; }); $hash{"tako"} = "ika"; if(!exists($hash{"tako"}) || scalar(keys(%hash)) != 1 || scalar(values(%hash)) != 1 || $hash{"tako"} ne "ika" || !delete($hash{"tako"})){ printf(STDERR "$0: $name: filter error: $Depot::errmsg\n"); return 1; } printf("ok\n"); # close the database printf("Closing the tied hash ... "); $depot = undef; untie(%hash); printf("ok\n"); printf("all ok\n\n"); return 0; } # execute main $0 =~ s/.*\///; exit(main()); # END OF FILE qdbm-1.8.78/perl/villa/0000755000175000017500000000000010705266453013625 5ustar mikiomikioqdbm-1.8.78/perl/villa/MANIFEST0000644000175000017500000000006007727054324014754 0ustar mikiomikioMANIFEST Makefile.PL Villa.pm Villa.xs plvltest qdbm-1.8.78/perl/villa/plvltest0000755000175000017500000001764510445202074015433 0ustar mikiomikio#! /usr/bin/perl -w #================================================================================================= # Test cases of Villa for Perl # Copyright (C) 2000-2005 Mikio Hirabayashi # This file is part of QDBM, Quick Database Manager. # QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU # Lesser General Public License as published by the Free Software Foundation; either version # 2.1 of the License or any later version. QDBM is distributed in the hope that it will be # useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more # details. # You should have received a copy of the GNU Lesser General Public License along with QDBM; if # not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA # 02111-1307 USA. #================================================================================================= use strict; use warnings; use ExtUtils::testlib; use Villa; # main routine sub main { my($rv); (scalar(@ARGV) >= 1) || usage(); if($ARGV[0] eq "write"){ $rv = runwrite(); } elsif($ARGV[0] eq "read"){ $rv = runread(); } elsif($ARGV[0] eq "tie"){ $rv = runtie(); } else { usage(); } return $rv; } # print the usage and exit sub usage { printf(STDERR "$0: test cases for Villa for Perl\n"); printf(STDERR "\n"); printf(STDERR "usage:\n"); printf(STDERR " $0 write name rnum\n"); printf(STDERR " $0 read name\n"); printf(STDERR " $0 tie name\n"); printf(STDERR "\n"); exit(1); } # parse arguments of write command sub runwrite { my($name, $rnum, $i, $rv); for($i = 1; $i < scalar(@ARGV); $i++){ if(!defined($name) && $ARGV[$i] =~ m/^-/){ usage(); } elsif(!defined($name)){ $name = $ARGV[$i]; } elsif(!defined($rnum)){ $rnum = $ARGV[$i]; } else { usage(); } } (defined($name) && defined($rnum)) || usage(); ($name && $rnum > 0) || usage(); $rv = dowrite($name, $rnum); return $rv; } # parse arguments of read command sub runread { my($name, $i, $rv); for($i = 1; $i < scalar(@ARGV); $i++){ if(!defined($name) && $ARGV[$i] =~ m/^-/){ usage(); } elsif(!defined($name)){ $name = $ARGV[$i]; } else { usage(); } } (defined($name)) || usage(); ($name) || usage(); $rv = doread($name); return $rv; } # parse arguments of tie command sub runtie { my($name, $i, $rv); for($i = 1; $i < scalar(@ARGV); $i++){ if(!defined($name) && $ARGV[$i] =~ m/^-/){ usage(); } elsif(!defined($name)){ $name = $ARGV[$i]; } else { usage(); } } (defined($name)) || usage(); ($name) || usage(); $rv = dotie($name); return $rv; } # perform write command sub dowrite { my($name, $rnum) = @_; my($i, $villa, $buf, $err); printf("\n name=$name rnum=$rnum\n\n"); # open a database if(!($villa = new Villa($name, Villa::OWRITER | Villa::OCREAT | Villa::OTRUNC))){ printf(STDERR "$0: $name: open error: $Villa::errmsg\n"); return 1; } # loop for each record $err = 0; $| = 1; for($i = 1; $i <= $rnum; $i++){ $buf = sprintf("%08d", $i); # store a record if(!$villa->put($buf, $buf, Villa::DKEEP)){ printf(STDERR "$0: $name: put error: $Villa::errmsg\n"); $err = 1; last; } # print progression if($rnum > 250 && $i % ($rnum / 250) == 0){ print('.'); if($i == $rnum || $i % ($rnum / 10) == 0){ printf(" (%08d)\n", $i); } } } # close the database if(!$villa->close()){ printf(STDERR "$0: $name: close error: $Villa::errmsg\n"); return 1; } ($err) || printf("ok\n\n"); return $err ? 1 : 0; } # perform read command sub doread { my($name) = @_; my($i, $villa, $rnum, $buf, $err); printf("\n name=$name\n\n"); # open a database if(!($villa = new Villa($name))){ printf(STDERR "$0: $name: open error: $Villa::errmsg\n"); return 1; } # get the number of records $rnum = $villa->rnum(); # loop for each record $err = 0; $| = 1; for($i = 1; $i <= $rnum; $i++){ $buf = sprintf("%08d", $i); # store a record if(!$villa->get($buf)){ printf(STDERR "$0: $name: get error: $Villa::errmsg\n"); $err = 1; last; } # print progression if($rnum > 250 && $i % ($rnum / 250) == 0){ print('.'); if($i == $rnum || $i % ($rnum / 10) == 0){ printf(" (%08d)\n", $i); } } } # close the database if(!$villa->close()){ printf(STDERR "$0: $name: close error: $Villa::errmsg\n"); return 1; } ($err) || printf("ok\n\n"); return $err ? 1 : 0; } # perform tie command sub dotie { my($name) = @_; my($LOOPNUM) = 100; my($i, $villa, $rnum, %hash, $buf, $key, $val); printf("\n name=$name\n\n"); $| = 1; # open the database printf("Creating a database with tied hash ... "); if(!($villa = tie(%hash, "Villa", $name, Villa::OWRITER | Villa::OCREAT | Villa::OTRUNC))){ printf(STDERR "$0: $name: open error: $Villa::errmsg\n"); return 1; } printf("ok\n"); # store records printf("Storing records into tied hash ... "); for($i = 1; $i <= $LOOPNUM; $i++){ $buf = sprintf("%08d", $i); if(!($hash{$buf} = $buf)){ printf(STDERR "$0: $name: store error: $Villa::errmsg\n"); return 1; } } printf("ok\n"); # retrieve records printf("Retrieving records in tied hash ... "); for($i = 1; $i <= $LOOPNUM; $i++){ $buf = sprintf("%08d", $i); if(!$hash{$buf}){ printf(STDERR "$0: $name: fetch error: $Villa::errmsg\n"); return 1; } } printf("ok\n"); # traverse records printf("Traversing records in tied hash ... "); $i = 0; while(($key, $val) = each(%hash)){ if($key ne $val){ printf(STDERR "$0: $name: each error: $Villa::errmsg\n"); return 1; } $i++; } if($i != $LOOPNUM){ printf(STDERR "$0: $name: each error: $Villa::errmsg\n"); return 1; } printf("ok\n"); # delete a record printf("Deleting a record in tied hash ... "); $buf = sprintf("%08d", $LOOPNUM / 2); if(!(delete $hash{$buf}) || scalar(keys(%hash)) != $LOOPNUM - 1){ printf(STDERR "$0: $name: delete error: $Villa::errmsg\n"); return 1; } printf("ok\n"); # clear the hash printf("Clear a record in tied hash ... "); %hash = (); if(scalar(keys(%hash)) != 0){ printf(STDERR "$0: $name: clear error: $Villa::errmsg\n"); return 1; } printf("ok\n"); # test filters printf("Testing filters ... "); $villa->filter_store_key(sub { s/$/\0/; }); $villa->filter_store_value(sub { s/$/\0/; }); $villa->filter_fetch_key(sub { s/\0$//; }); $villa->filter_fetch_value(sub { s/\0$//; }); $hash{"tako"} = "ika"; if(!exists($hash{"tako"}) || scalar(keys(%hash)) != 1 || scalar(values(%hash)) != 1 || $hash{"tako"} ne "ika" || !delete($hash{"tako"})){ printf(STDERR "$0: $name: filter error: $Villa::errmsg\n"); return 1; } printf("ok\n"); # close the database printf("Closing the tied hash ... "); $villa = undef; untie(%hash); printf("ok\n"); printf("all ok\n\n"); return 0; } # execute main $0 =~ s/.*\///; exit(main()); # END OF FILE qdbm-1.8.78/perl/villa/Makefile.PL0000644000175000017500000000055107703744526015606 0ustar mikiomikio#================================================================================================= # Script for MakeMaker #================================================================================================= use ExtUtils::MakeMaker; # Create Makefile WriteMakefile( 'NAME' => 'Villa', 'VERSION_FROM' => 'Villa.pm', ); # END OF FILE qdbm-1.8.78/perl/villa/Villa.pm0000644000175000017500000006504310445176553015244 0ustar mikiomikio#================================================================================================= # Perl API of Villa, the basic API of QDBM # Copyright (C) 2000-2005 Mikio Hirabayashi # This file is part of QDBM, Quick Database Manager. # QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU # Lesser General Public License as published by the Free Software Foundation; either version # 2.1 of the License or any later version. QDBM is distributed in the hope that it will be # useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more # details. # You should have received a copy of the GNU Lesser General Public License along with QDBM; if # not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA # 02111-1307 USA. #================================================================================================= package Villa; use strict; use warnings; require Tie::Hash; require Exporter; require XSLoader; our @ISA = qw(Tie::Hash Exporter); our $VERSION = '1.0'; XSLoader::load('Villa', $VERSION); use constant TRUE => 1; # boolean true use constant FALSE => 0; # boolean false use constant OREADER => 1 << 0; # open as a reader use constant OWRITER => 1 << 1; # open as a writer use constant OCREAT => 1 << 2; # a writer creating use constant OTRUNC => 1 << 3; # a writer truncating use constant ONOLCK => 1 << 4; # open without locking use constant OLCKNB => 1 << 5; # lock without blocking use constant OZCOMP => 1 << 6; # compress leaves with ZLIB use constant OYCOMP => 1 << 7; # compress leaves with LZO use constant OXCOMP => 1 << 8; # compress leaves with BZIP2 use constant CMPLEX => 0; # compare in lexical order use constant CMPDEC => 1; # compare decimal strings use constant DOVER => 0; # overwrite an existing value use constant DKEEP => 1; # keep an existing value use constant DCAT => 2; # concatenate values use constant DDUP => 3; # allow duplication of records use constant DDUPR => 4; # allow duplication with reverse order use constant JFORWARD => 0; # step forward use constant JBACKWARD => 1; # step backward use constant CPCURRENT => 0; # overwrite the current record use constant CPBEFORE => 1; # insert before the current record use constant CPAFTER => 2; # insert after the current record my(%handles) = (); # table of database names our($errmsg) = "no error"; # message of the last error #================================================================================================= # public objects #================================================================================================= ## # use Villa; # Module `Villa' should be loaded in application codes. # An instance of the class `Villa' is used as a database handle. # ## # $Villa::errmsg; # Global Variable: The message of the last happened error. # ## # $villa = new Villa($name, $omode, $cmode); # Constructor: Get the database handle. # `$name' specifies the name of a database file. # `$omode' specifies the connection mode: `Villa::OWRITER' as a writer, `Villa::OREADER' as a # reader. If the mode is `Villa::OWRITER', the following may be added by bitwise or: # `Villa::OCREAT', which means it creates a new database if not exist, `Villa::OTRUNC', which # means it creates a new database regardless if one exists, `Villa::OZCOMP', which means leaves # in the database are compressed with ZLIB, `Villa::OYCOMP', which means leaves in the database # are compressed with LZO, `Villa::OXCOMP', which means leaves in the database are compressed # with BZIP2. Both of `Villa::OREADER' and `Villa::OWRITER' can be added to by bitwise or: # `Villa::ONOLCK', which means it opens a database file without file locking, or `Villa::OLCKNB', # which means locking is performed without blocking. If it is undef, `Villa::OREADER' is # specified. # `$cmode' specifies the comparing function: `Villa::CMPLEX' comparing keys in lexical order, # `Villa::CMPDEC' comparing keys as decimal strings. The comparing function should be kept # same in the life of a database. # The return value is the database handle or undef if it is not successful. # While connecting as a writer, an exclusive lock is invoked to the database file. # While connecting as a reader, a shared lock is invoked to the database file. The thread # blocks until the lock is achieved. `Villa::OZCOMP', `Villa::OYCOMP', and `Villa::OXCOMP' are # available only if QDBM was built each with ZLIB, LZO, and BZIP2 enabled. If `Villa::ONOLCK' # is used, the application is responsible for exclusion control. # sub new { my($class) = shift; my($name) = shift; my($omode) = shift; my($cmode) = shift; (defined($name) && length($name) > 0 && scalar(@_) == 0) || return undef; (!$handles{$name}) || return undef; (defined($omode)) || ($omode = OREADER); (defined($cmode)) || ($cmode = CMPLEX); my($villa) = plvlopen($name, $omode, $cmode); $errmsg = plvlerrmsg(); ($villa > 0) || return undef; $handles{$name} = $villa; my $self = [$name, TRUE, undef, undef, undef, undef]; bless($self, $class); return $self; } ## # $bool = $villa->close(); # Method: Close the database handle. # If successful, the return value is true, else, it is false. # Because the region of a closed handle is released, it becomes impossible to use the handle. # Updating a database is assured to be written when the handle is closed. If a writer opens # a database but does not close it appropriately, the database will be broken. If the # transaction is activated and not committed, it is aborted. # sub close { my($self) = shift; ($$self[1]) || return FALSE; (scalar(@_) == 0) || return FALSE; $$self[1] = FALSE; my($villa) = $handles{$$self[0]}; my($rv) = plvlclose($villa); $errmsg = plvlerrmsg(); delete($handles{$$self[0]}); return $rv; } ## # $bool = $villa->put($key, $val, $dmode); # Method: Store a record. # `$key' specifies a key. If it is undef, this method has no effect. # `$val' specifies a value. If it is undef, this method has no effect. # `$dmode' specifies behavior when the key overlaps, by the following values: `Villa::DOVER', # which means the specified value overwrites the existing one, `Villa::DKEEP', which means the # existing value is kept, `Villa::DCAT', which means the specified value is concatenated at the # end of the existing value, `Villa::DDUP', which means duplication of keys is allowed and the # specified value is added as the last one, `Villa::DDUPR', which means duplication of keys is # allowed and the specified value is added as the first one. If it is undef, `Villa::DOVER' is # specified. # If successful, the return value is true, else, it is false. # The cursor becomes unavailable due to updating database. # sub put { my($self) = shift; ($$self[1]) || return FALSE; my($key) = shift; my($val) = shift; my($dmode) = shift; (scalar(@_) == 0) || return FALSE; (defined($key) && defined($val)) || return FALSE; (defined($dmode)) || ($dmode = DOVER); my($villa) = $handles{$$self[0]}; if($$self[2]){ local($_) = $key; $$self[2](); $key = $_; } if($$self[3]){ local($_) = $val; $$self[3](); $val = $_; } my($rv) = plvlput($villa, $key, length($key), $val, length($val), $dmode); $errmsg = plvlerrmsg(); return $rv; } ## # $bool = $villa->out($key); # Method: Delete a record. # `$key' specifies a key. If it is undef, this method has no effect. # If successful, the return value is true, else, it is false. False is returned when no # record corresponds to the specified key. # When the key of duplicated records is specified, the first record of the same key is deleted. # The cursor becomes unavailable due to updating database. # sub out { my($self) = shift; ($$self[1]) || return FALSE; my($key) = shift; (scalar(@_) == 0) || return FALSE; (defined($key)) || return FALSE; my($villa) = $handles{$$self[0]}; if($$self[2]){ local($_) = $key; $$self[2](); $key = $_; } my($rv) = plvlout($villa, $key, length($key)); $errmsg = plvlerrmsg(); return $rv; } ## # $str = $villa->get($key); # Method: Retrieve a record. # `$key' specifies a key. If it is undef, this method has no effect. # If successful, the return value is a scalar of the value of the corresponding record, else, it # is undef. undef is returned when no record corresponds to the specified key. # When the key of duplicated records is specified, the value of the first record of the same key # is selected. # sub get { my($self) = shift; ($$self[1]) || return undef; my($key) = shift; (scalar(@_) == 0) || return undef; (defined($key)) || return undef; my($villa) = $handles{$$self[0]}; if($$self[2]){ local($_) = $key; $$self[2](); $key = $_; } my($rv) = plvlget($villa, $key, length($key)); $errmsg = plvlerrmsg(); if($rv && $$self[5]){ local($_) = $rv; $$self[5](); $rv = $_; } return $rv; } ## # $num = $villa->vsiz($key); # Method: Get the size of the value of a record. # `$key' specifies a key. If it is undef, this method has no effect. # The return value is the size of the value of the corresponding record. If no record # corresponds, -1 is returned. If multiple records correspond, the size of the first is # returned. # sub vsiz { my($self) = shift; ($$self[1]) || return 0; my($key) = shift; (scalar(@_) == 0) || return 0; (defined($key)) || return 0; my($villa) = $handles{$$self[0]}; if($$self[2]){ local($_) = $key; $$self[2](); $key = $_; } my($rv) = plvlvsiz($villa, $key, length($key)); $errmsg = plvlerrmsg(); return $rv; } ## # $num = $villa->vnum($key); # Method: Get the number of records corresponding a key. # `$key' specifies a key. If it is undef, this method has no effect. # If successful, the return value is the size of the value of the corresponding record, else, # it is 0. # sub vnum { my($self) = shift; ($$self[1]) || return 0; my($key) = shift; (scalar(@_) == 0) || return 0; (defined($key)) || return 0; my($villa) = $handles{$$self[0]}; if($$self[2]){ local($_) = $key; $$self[2](); $key = $_; } my($rv) = plvlvnum($villa, $key, length($key)); $errmsg = plvlerrmsg(); return $rv; } ## # $bool = $villa->curfirst(); # Method: Move the cursor to the first record. # If successful, the return value is true, else, it is false. False is returned if there is # no record in the database. # sub curfirst { my($self) = shift; ($$self[1]) || return FALSE; (scalar(@_) == 0) || return FALSE; my($villa) = $handles{$$self[0]}; my($rv) = plvlcurfirst($villa); $errmsg = plvlerrmsg(); return $rv; } ## # $bool = $villa->curlast(); # Method: Move the cursor to the last record. # If successful, the return value is true, else, it is false. False is returned if there is # no record in the database. # sub curlast { my($self) = shift; ($$self[1]) || return FALSE; (scalar(@_) == 0) || return FALSE; my($villa) = $handles{$$self[0]}; my($rv) = plvlcurlast($villa); $errmsg = plvlerrmsg(); return $rv; } ## # $bool = $villa->curprev(); # Method: Move the cursor to the previous record. # If successful, the return value is true, else, it is false. False is returned if there is # no previous record. # sub curprev { my($self) = shift; ($$self[1]) || return FALSE; (scalar(@_) == 0) || return FALSE; my($villa) = $handles{$$self[0]}; my($rv) = plvlcurprev($villa); $errmsg = plvlerrmsg(); return $rv; } ## # $bool = $villa->curnext(); # Method: Move the cursor to the next record. # If successful, the return value is true, else, it is false. False is returned if there is # no next record. # sub curnext { my($self) = shift; ($$self[1]) || return FALSE; (scalar(@_) == 0) || return FALSE; my($villa) = $handles{$$self[0]}; my($rv) = plvlcurnext($villa); $errmsg = plvlerrmsg(); return $rv; } ## # $bool = $villa->curjump($key, $jmode); # Method: Move the cursor to a position around a record. # `$key' specifies a key. If it is undef, this method has no effect. # `$jmode' specifies detail adjustment: `Villa::JFORWARD', which means that the cursor is set # to the first record of the same key and that the cursor is set to the next substitute if # completely matching record does not exist, `Villa::JBACKWARD', which means that the cursor # is set to the last record of the same key and that the cursor is set to the previous # substitute if completely matching record does not exist. If it is undef, `Villa::JFORWARD' # is specified. # If successful, the return value is true, else, it is false. False is returned if there is # no record corresponding the condition. # sub curjump { my($self) = shift; ($$self[1]) || return FALSE; my($key) = shift; my($jmode) = shift; (scalar(@_) == 0) || return FALSE; (defined($key)) || return FALSE; (defined($jmode)) || ($jmode = JFORWARD); my($villa) = $handles{$$self[0]}; if($$self[2]){ local($_) = $key; $$self[2](); $key = $_; } my($rv) = plvlcurjump($villa, $key, length($key), $jmode); $errmsg = plvlerrmsg(); return $rv; } ## # $str = $villa->curkey(); # Method: Get the key of the record where the cursor is. # If successful, the return value is a scalar of the key of the corresponding record, else, it # is undef. undef is returned when no record corresponds to the cursor. # sub curkey { my($self) = shift; ($$self[1]) || return undef; (scalar(@_) == 0) || return undef; my($villa) = $handles{$$self[0]}; my($rv) = plvlcurkey($villa); $errmsg = plvlerrmsg(); if($rv && $$self[4]){ local($_) = $rv; $$self[4](); $rv = $_; } return $rv; } ## # $str = $villa->curval(); # Method: Get the value of the record where the cursor is. # If successful, the return value is a scalar of the value of the corresponding record, else, it # is undef. undef is returned when no record corresponds to the cursor. # sub curval { my($self) = shift; ($$self[1]) || return undef; (scalar(@_) == 0) || return undef; my($villa) = $handles{$$self[0]}; my($rv) = plvlcurval($villa); $errmsg = plvlerrmsg(); if($rv && $$self[5]){ local($_) = $rv; $$self[5](); $rv = $_; } return $rv; } ## # $bool = $villa->curput($val, $cpmode); # Method: Insert a record around the cursor. # `$val' specifies a value. If it is undef, this method has no effect. # `$cpmode' specifies detail adjustment: `Villa::CPCURRENT', which means that the value of the # current record is overwritten, `Villa::CPBEFORE', which means that a new record is inserted # before the current record, `Villa::CPAFTER', which means that a new record is inserted after # the current record. If it is undef, `Villa::CPCURRENT' is specified. # If successful, the return value is true, else, it is false. False is returned when no record # corresponds to the cursor. # After insertion, the cursor is moved to the inserted record. # sub curput { my($self) = shift; ($$self[1]) || return FALSE; my($val) = shift; my($cpmode) = shift; (scalar(@_) == 0) || return FALSE; (defined($val)) || return FALSE; (defined($cpmode)) || ($cpmode = CPCURRENT); my($villa) = $handles{$$self[0]}; if($$self[3]){ local($_) = $val; $$self[3](); $val = $_; } my($rv) = plvlcurput($villa, $val, length($val), $cpmode); $errmsg = plvlerrmsg(); return $rv; } ## # $bool = $villa->curout(); # Method: Delete the record where the cursor is. # If successful, the return value is true, else, it is false. False is returned when no record # corresponds to the cursor. # After deletion, the cursor is moved to the next record if possible. # sub curout { my($self) = shift; ($$self[1]) || return FALSE; (scalar(@_) == 0) || return FALSE; my($villa) = $handles{$$self[0]}; my($rv) = plvlcurout($villa); $errmsg = plvlerrmsg(); return $rv; } ## # $bool = $villa->settuning($lrecmax, $nidxmax, $lcnum, $ncnum); # Method: Set alignment of the database handle. # `$lrecmax' specifies the max number of records in a leaf node of B+ tree. If it is undef or # not more than 0, the default value is specified. # `$nidxmax' specifies the max number of indexes in a non-leaf node of B+ tree. If it is undef # or not more than 0, the default value is specified. # `$lcnum' specifies the max number of caching leaf nodes. If it is undef or not more than 0, # the default value is specified. # `$ncnum' specifies the max number of caching non-leaf nodes. If it is undef or not more than # 0, the default value is specified. # If successful, the return value is true, else, it is false. # The default setting is equivalent to `vlsettuning(49, 192, 1024, 512)'. Because tuning # parameters are not saved in a database, you should specify them every opening a database. # sub settuning { my($self) = shift; ($$self[1]) || return FALSE; my($lrecmax) = shift; my($nidxmax) = shift; my($lcnum) = shift; my($ncnum) = shift; (defined($lrecmax)) || ($lrecmax = -1); (defined($nidxmax)) || ($nidxmax = -1); (defined($lcnum)) || ($lcnum = -1); (defined($ncnum)) || ($ncnum = -1); (scalar(@_) == 0) || return FALSE; my($villa) = $handles{$$self[0]}; plvlsettuning($villa, $lrecmax, $nidxmax, $lcnum, $ncnum); return TRUE; } ## # $bool = $villa->sync(); # Method: Synchronize updating contents with the file and the device. # If successful, the return value is true, else, it is false. # This method is useful when another process uses the connected database file. This method # should not be used while the transaction is activated. # sub sync { my($self) = shift; ($$self[1]) || return FALSE; (scalar(@_) == 0) || return FALSE; my($villa) = $handles{$$self[0]}; my($rv) = plvlsync($villa); $errmsg = plvlerrmsg(); return $rv; } ## # $bool = $villa->optimize(); # Method: Optimize the database. # If successful, the return value is true, else, it is false. # In an alternating succession of deleting and storing with overwrite or concatenate, # dispensable regions accumulate. This method is useful to do away with them. This method # should not be used while the transaction is activated. # sub optimize { my($self) = shift; ($$self[1]) || return FALSE; (scalar(@_) == 0) || return FALSE; my($villa) = $handles{$$self[0]}; my($rv) = plvloptimize($villa); $errmsg = plvlerrmsg(); return $rv; } ## # $num = $villa->fsiz(); # Method: Get the size of the database file. # If successful, the return value is the size of the database file, else, it is -1. # Because of the I/O buffer, the return value may be less than the real size. # sub fsiz { my($self) = shift; ($$self[1]) || return -1; (scalar(@_) == 0) || return -1; my($villa) = $handles{$$self[0]}; my($rv) = plvlfsiz($villa); $errmsg = plvlerrmsg(); return $rv; } ## # $num = $villa->rnum(); # Method: Get the number of the records stored in the database. # If successful, the return value is the number of the records stored in the database, else, # it is -1. # sub rnum { my($self) = shift; ($$self[1]) || return -1; (scalar(@_) == 0) || return -1; my($villa) = $handles{$$self[0]}; my($rv) = plvlrnum($villa); $errmsg = plvlerrmsg(); return $rv; } ## # $bool = $villa->writable(); # Method: Check whether the database handle is a writer or not. # The return value is true if the handle is a writer, false if not. # sub writable { my($self) = shift; ($$self[1]) || return FALSE; (scalar(@_) == 0) || return FALSE; my($villa) = $handles{$$self[0]}; my($rv) = plvlwritable($villa); $errmsg = plvlerrmsg(); return $rv; } ## # $bool = $villa->fatalerror(); # Method: Check whether the database has a fatal error or not. # The return value is true if the database has a fatal error, false if not. # sub fatalerror { my($self) = shift; ($$self[1]) || return FALSE; (scalar(@_) == 0) || return FALSE; my($villa) = $handles{$$self[0]}; my($rv) = plvlfatalerror($villa); $errmsg = plvlerrmsg(); return $rv; } ## # $bool = $villa->tranbegin(); # Method: Begin the transaction. # If successful, the return value is true, else, it is false. # Only one transaction can be activated with a database handle at the same time. # sub tranbegin { my($self) = shift; ($$self[1]) || return FALSE; (scalar(@_) == 0) || return FALSE; my($villa) = $handles{$$self[0]}; my($rv) = plvltranbegin($villa); $errmsg = plvlerrmsg(); return $rv; } ## # $bool = $villa->trancommit(); # Method: Commit the transaction. # If successful, the return value is true, else, it is false. # Updating a database in the transaction is fixed when it is committed successfully. # sub trancommit { my($self) = shift; ($$self[1]) || return FALSE; (scalar(@_) == 0) || return FALSE; my($villa) = $handles{$$self[0]}; my($rv) = plvltrancommit($villa); $errmsg = plvlerrmsg(); return $rv; } ## # $bool = $villa->tranabort(); # Method: Abort the transaction. # If successful, the return value is true, else, it is false. # Updating a database in the transaction is discarded when it is aborted. The state of the # database is rollbacked to before transaction. # sub tranabort { my($self) = shift; ($$self[1]) || return FALSE; (scalar(@_) == 0) || return FALSE; my($villa) = $handles{$$self[0]}; my($rv) = plvltranabort($villa); $errmsg = plvlerrmsg(); return $rv; } ## #: Called automatically by the garbage collector. # Destructor: DESTROY: Release the resources. # If the database handle is not closed yet, it is closed. # sub DESTROY { my($self) = shift; $self->close(); } ## # $villa = tie(%hash, "Villa", $name, $omode, $cmp); # Tying Function: TIEHASH: Get the database handle. # sub TIEHASH { my($class, $name, $omode, $cmp) = @_; (defined($name)) || return undef; (defined($omode)) || ($omode = OWRITER | OCREAT); return $class->new($name, $omode, $cmp); } ## # $bool = ($hash{$key} = $val); # Tying Function: STORE: Store a record with overwrite. # sub STORE { my($self, $key, $val) = @_; ($$self[1]) || return FALSE; (defined($key) && defined($val)) || return FALSE; my($villa) = $handles{$$self[0]}; if($$self[2]){ local($_) = $key; $$self[2](); $key = $_; } if($$self[3]){ local($_) = $val; $$self[3](); $val = $_; } my($rv) = plvlput($villa, $key, length($key), $val, length($val), DOVER); ($rv == 0) && ($errmsg = plvlerrmsg()); return $rv; } ## # $bool = delete($hash{$key}); # Tying Function: DELETE: Delete a record. # sub DELETE { my($self, $key) = @_; ($$self[1]) || return FALSE; (defined($key)) || return FALSE; my($villa) = $handles{$$self[0]}; if($$self[2]){ local($_) = $key; $$self[2](); $key = $_; } my($rv) = plvlout($villa, $key, length($key)); $errmsg = plvlerrmsg(); return $rv; } ## # $bool = (%hash = ()); # Tying Function: CLEAR: Delete all records. # sub CLEAR { my($self) = shift; my($key); while($self->curfirst()){ ($key = $self->curkey()) || return FALSE; ($self->out($key)) || return FALSE; } return TRUE; } ## # $str = $hash{$key}; # Tying Function: FETCH: Retrieve whole value of a record. # sub FETCH { my($self, $key) = @_; ($$self[1]) || return undef; (defined($key)) || return undef; my($villa) = $handles{$$self[0]}; if($$self[2]){ local($_) = $key; $$self[2](); $key = $_; } my($rv) = plvlget($villa, $key, length($key)); $errmsg = plvlerrmsg(); if($rv && $$self[5]){ local($_) = $rv; $$self[5](); $rv = $_; } return $rv; } ## # $bool = exists($hash{$val}); # Tying Function: EXISTS: Check whether a record exists or not. # sub EXISTS { my($self) = shift; my($key) = shift; return $self->vnum($key) > 0 ? TRUE : FALSE; } ## #: Called automatically by keys(), each(), and so on. # Tying Function: FIRSTKEY: Get the first key. # sub FIRSTKEY { my($self) = shift; ($self->curfirst()) || return undef; return $self->curkey(); } ## #: Called automatically by keys(), each(), and so on. # Tying Function: NEXTKEY: Get the next key. # sub NEXTKEY { my($self) = shift; ($self->curnext()) || return undef; return $self->curkey(); } ## # $func = $villa->filter_store_key(\&nf); # Method: set a filter invoked when writing a key. # `\&nf' specifies the reference of a filter function proofing `$_'. If it is undef, the # current filter function is cleared. # The return value is the old filter function. # sub filter_store_key { my($self) = shift; my($nf) = shift; my($of) = $$self[2]; $$self[2] = $nf; return $of; } ## # $func = $villa->filter_store_value(\&nf); # Method: set a filter invoked when writing a value. # `\&nf' specifies the reference of a filter function proofing `$_'. If it is undef, the # current filter function is cleared. # The return value is the old filter function. # sub filter_store_value { my($self) = shift; my($nf) = shift; my($of) = $$self[3]; $$self[3] = $nf; return $of; } ## # $func = $villa->filter_fetch_key(\&nf); # Method: set a filter invoked when reading a key. # `\&nf' specifies the reference of a filter function proofing `$_'. If it is undef, the # current filter function is cleared. # The return value is the old filter function. # sub filter_fetch_key { my($self) = shift; my($nf) = shift; my($of) = $$self[4]; $$self[4] = $nf; return $of; } ## # $func = $villa->filter_fetch_value(\&nf); # Method: set a filter invoked when reading a value. # `\&nf' specifies the reference of a filter function proofing `$_'. If it is undef, the # current filter function is cleared. # The return value is the old filter function. # sub filter_fetch_value { my($self) = shift; my($nf) = shift; my($of) = $$self[5]; $$self[5] = $nf; return $of; } TRUE; # return success code # END OF FILE qdbm-1.8.78/perl/villa/Villa.xs0000644000175000017500000001143110443773002015240 0ustar mikiomikio/************************************************************************************************* * Villa.c * Copyright (C) 2000-2005 Mikio Hirabayashi * This file is part of QDBM, Quick Database Manager. * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU * Lesser General Public License as published by the Free Software Foundation; either version * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * You should have received a copy of the GNU Lesser General Public License along with QDBM; if * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. *************************************************************************************************/ #include "EXTERN.h" #include "perl.h" #include "XSUB.h" #include #include #include #include MODULE = Villa PACKAGE = Villa PROTOTYPES: DISABLE ##================================================================================================ ## public objects ##================================================================================================ const char * plvlerrmsg() CODE: RETVAL = dperrmsg(dpecode); OUTPUT: RETVAL void * plvlopen(name, omode, cmode) char * name int omode int cmode PREINIT: VLCFUNC cmp; CODE: switch(cmode){ case 1: cmp = VL_CMPDEC; break; default: cmp = VL_CMPLEX; break; } RETVAL = vlopen(name, omode, cmp); OUTPUT: RETVAL int plvlclose(villa) void *villa CODE: RETVAL = vlclose(villa); OUTPUT: RETVAL int plvlput(villa, kbuf, ksiz, vbuf, vsiz, dmode) void * villa char * kbuf int ksiz char * vbuf int vsiz int dmode CODE: RETVAL = vlput(villa, kbuf, ksiz, vbuf, vsiz, dmode); OUTPUT: RETVAL int plvlout(villa, kbuf, ksiz) void * villa char * kbuf int ksiz CODE: RETVAL = vlout(villa, kbuf, ksiz); OUTPUT: RETVAL void plvlget(villa, kbuf, ksiz) void * villa char * kbuf int ksiz PREINIT: const char *vbuf; int vsiz; PPCODE: vbuf = vlgetcache(villa, kbuf, ksiz, &vsiz); if(!vbuf) XSRETURN_UNDEF; XPUSHs(sv_2mortal(newSVpv(vbuf, vsiz))); XSRETURN(1); int plvlvsiz(villa, kbuf, ksiz) void * villa char * kbuf int ksiz CODE: RETVAL = vlvsiz(villa, kbuf, ksiz); OUTPUT: RETVAL int plvlvnum(villa, kbuf, ksiz) void * villa char * kbuf int ksiz CODE: RETVAL = vlvnum(villa, kbuf, ksiz); OUTPUT: RETVAL int plvlcurfirst(villa) void * villa CODE: RETVAL = vlcurfirst(villa); OUTPUT: RETVAL int plvlcurlast(villa) void * villa CODE: RETVAL = vlcurlast(villa); OUTPUT: RETVAL int plvlcurprev(villa) void * villa CODE: RETVAL = vlcurprev(villa); OUTPUT: RETVAL int plvlcurnext(villa) void * villa CODE: RETVAL = vlcurnext(villa); OUTPUT: RETVAL int plvlcurjump(villa, kbuf, ksiz, jmode) void * villa char * kbuf int ksiz int jmode CODE: RETVAL = vlcurjump(villa, kbuf, ksiz, jmode); OUTPUT: RETVAL void plvlcurkey(villa) void * villa PREINIT: const char *kbuf; int ksiz; PPCODE: kbuf = vlcurkeycache(villa, &ksiz); if(!kbuf) XSRETURN_UNDEF; XPUSHs(sv_2mortal(newSVpv(kbuf, ksiz))); XSRETURN(1); void plvlcurval(villa) void * villa PREINIT: const char *vbuf; int vsiz; PPCODE: vbuf = vlcurvalcache(villa, &vsiz); if(!vbuf) XSRETURN_UNDEF; XPUSHs(sv_2mortal(newSVpv(vbuf, vsiz))); XSRETURN(1); int plvlcurput(villa, vbuf, vsiz, cpmode) void * villa char * vbuf int vsiz int cpmode CODE: RETVAL = vlcurput(villa, vbuf, vsiz, cpmode); OUTPUT: RETVAL int plvlcurout(villa) void * villa CODE: RETVAL = vlcurout(villa); OUTPUT: RETVAL void plvlsettuning(villa, lrecmax, nidxmax, lcnum, ncnum) void * villa int lrecmax int nidxmax int lcnum int ncnum CODE: vlsettuning(villa, lrecmax, nidxmax, lcnum, ncnum); int plvlsync(villa) void * villa CODE: RETVAL = vlsync(villa); OUTPUT: RETVAL int plvloptimize(villa) void * villa CODE: RETVAL = vloptimize(villa); OUTPUT: RETVAL int plvlfsiz(villa) void * villa CODE: RETVAL = vlfsiz(villa); OUTPUT: RETVAL int plvlrnum(villa) void * villa CODE: RETVAL = vlrnum(villa); OUTPUT: RETVAL int plvlwritable(villa) void * villa CODE: RETVAL = vlwritable(villa); OUTPUT: RETVAL int plvlfatalerror(villa) void * villa CODE: RETVAL = vlfatalerror(villa); OUTPUT: RETVAL int plvltranbegin(villa) void * villa CODE: RETVAL = vltranbegin(villa); OUTPUT: RETVAL int plvltrancommit(villa) void * villa CODE: RETVAL = vltrancommit(villa); OUTPUT: RETVAL int plvltranabort(villa) void * villa CODE: RETVAL = vltranabort(villa); OUTPUT: RETVAL ## END OF FILE qdbm-1.8.78/perl/configure0000755000175000017500000033677111426320065014435 0ustar mikiomikio#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.65 for qdbm-perl 1.0.0. # # # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, # 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, # Inc. # # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi " as_required="as_fn_return () { (exit \$1); } as_fn_success () { as_fn_return 0; } as_fn_failure () { as_fn_return 1; } as_fn_ret_success () { return 0; } as_fn_ret_failure () { return 1; } exitcode=0 as_fn_success || { exitcode=1; echo as_fn_success failed.; } as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : else exitcode=1; echo positional parameters were not saved. fi test x\$exitcode = x0 || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1" if (eval "$as_required") 2>/dev/null; then : as_have_required=yes else as_have_required=no fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. as_shell=$as_dir/$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : CONFIG_SHELL=$as_shell as_have_required=yes if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : break 2 fi fi done;; esac as_found=false done $as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : CONFIG_SHELL=$SHELL as_have_required=yes fi; } IFS=$as_save_IFS if test "x$CONFIG_SHELL" != x; then : # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV export CONFIG_SHELL exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"} fi if test x$as_have_required = xno; then : $as_echo "$0: This script requires a shell more modern than all" $as_echo "$0: the shells that I found on your system." if test x${ZSH_VERSION+set} = xset ; then $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" $as_echo "$0: be upgraded to zsh 4.3.4 or later." else $as_echo "$0: Please tell bug-autoconf@gnu.org about your system, $0: including any error possibly output before this $0: message. Then install a modern shell, or manually run $0: the script under such a shell if you do have one." fi exit 1 fi fi fi SHELL=${CONFIG_SHELL-/bin/sh} export SHELL # Unset more variables known to interfere with behavior of common tools. CLICOLOR_FORCE= GREP_OPTIONS= unset CLICOLOR_FORCE GREP_OPTIONS ## --------------------- ## ## M4sh Shell Functions. ## ## --------------------- ## # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error "cannot create directory $as_dir" } # as_fn_mkdir_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith # as_fn_error ERROR [LINENO LOG_FD] # --------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with status $?, using 1 if that was 0. as_fn_error () { as_status=$?; test $as_status -eq 0 && as_status=1 if test "$3"; then as_lineno=${as_lineno-"$2"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $1" >&$3 fi $as_echo "$as_me: error: $1" >&2 as_fn_exit $as_status } # as_fn_error if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits as_lineno_1=$LINENO as_lineno_1a=$LINENO as_lineno_2=$LINENO as_lineno_2a=$LINENO eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -p'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -p' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -p' fi else as_ln_s='cp -p' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi if test -x / >/dev/null 2>&1; then as_test_x='test -x' else if ls -dL / >/dev/null 2>&1; then as_ls_L_option=L else as_ls_L_option= fi as_test_x=' eval sh -c '\'' if test -d "$1"; then test -d "$1/."; else case $1 in #( -*)set "./$1";; esac; case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( ???[sx]*):;;*)false;;esac;fi '\'' sh ' fi as_executable_p=$as_test_x # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME='qdbm-perl' PACKAGE_TARNAME='qdbm-perl' PACKAGE_VERSION='1.0.0' PACKAGE_STRING='qdbm-perl 1.0.0' PACKAGE_BUGREPORT='' PACKAGE_URL='' ac_subst_vars='LTLIBOBJS LIBOBJS OBJEXT EXEEXT ac_ct_CC CPPFLAGS LDFLAGS CFLAGS CC target_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_URL PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL' ac_subst_files='' ac_user_opts=' enable_option_checking ' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS' # Initialize some variables set by options. ac_init_help= ac_init_version=false ac_unrecognized_opts= ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) as_fn_error "unrecognized option: \`$ac_option' Try \`$0 --help' for more information." ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) as_fn_error "invalid variable name: \`$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` as_fn_error "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) as_fn_error "unrecognized options: $ac_unrecognized_opts" ;; *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi # Check all directory arguments for consistency. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir do eval ac_val=\$$ac_var # Remove trailing slashes. case $ac_val in */ ) ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` eval $ac_var=\$ac_val;; esac # Be sure to have absolute directory names. case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac as_fn_error "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe $as_echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. If a cross compiler is detected then cross compile mode will be used." >&2 elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || as_fn_error "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || as_fn_error "pwd does not report name of working directory" # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." as_fn_error "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures qdbm-perl 1.0.0 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/qdbm-perl] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of qdbm-perl 1.0.0:";; esac cat <<\_ACEOF Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to the package provider. _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for guested configure. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF qdbm-perl configure 1.0.0 generated by GNU Autoconf 2.65 Copyright (C) 2009 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi ## ------------------------ ## ## Autoconf initialization. ## ## ------------------------ ## # ac_fn_c_try_compile LINENO # -------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} as_fn_set_status $ac_retval } # ac_fn_c_try_compile # ac_fn_c_try_link LINENO # ----------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} as_fn_set_status $ac_retval } # ac_fn_c_try_link cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by qdbm-perl $as_me 1.0.0, which was generated by GNU Autoconf 2.65. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. $as_echo "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) as_fn_append ac_configure_args1 " '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done { ac_configure_args0=; unset ac_configure_args0;} { ac_configure_args1=; unset ac_configure_args1;} # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo cat <<\_ASBOX ## ---------------- ## ## Cache variables. ## ## ---------------- ## _ASBOX echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo cat <<\_ASBOX ## ----------------- ## ## Output variables. ## ## ----------------- ## _ASBOX echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then cat <<\_ASBOX ## ------------------- ## ## File substitutions. ## ## ------------------- ## _ASBOX echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then cat <<\_ASBOX ## ----------- ## ## confdefs.h. ## ## ----------- ## _ASBOX echo cat confdefs.h echo fi test "$ac_signal" != 0 && $as_echo "$as_me: caught signal $ac_signal" $as_echo "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h $as_echo "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_URL "$PACKAGE_URL" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. ac_site_file1=NONE ac_site_file2=NONE if test -n "$CONFIG_SITE"; then ac_site_file1=$CONFIG_SITE elif test "x$prefix" != xNONE; then ac_site_file1=$prefix/share/config.site ac_site_file2=$prefix/etc/config.site else ac_site_file1=$ac_default_prefix/share/config.site ac_site_file2=$ac_default_prefix/etc/config.site fi for ac_site_file in "$ac_site_file1" "$ac_site_file2" do test "x$ac_site_file" = xNONE && continue if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 $as_echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 $as_echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 $as_echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then # differences in whitespace do not lead to failure. ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 $as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 $as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 $as_echo "$as_me: former value: \`$ac_old_val'" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 $as_echo "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 $as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} as_fn_error "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## ## -------------------- ## ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu # Building paths pathtmp="$PATH" PATH="$HOME/bin:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin" PATH="$PATH:/usr/ccs/bin:/usr/ucb:/usr/xpg4/bin:/usr/xpg6/bin:$pathtmp" LIBRARY_PATH="$HOME/lib:/usr/local/lib:$LIBRARY_PATH" LD_LIBRARY_PATH="$HOME/lib:/usr/local/lib:$LD_LIBRARY_PATH" CPATH="$HOME/include:/usr/local/include:$CPATH" export PATH LIBRARY_PATH LD_LIBRARY_PATH CPATH # Setting the default prefix if test "$prefix" = NONE then prefix=`perl -mConfig -e 'print $Config::Config{prefix}'` fi # Underlying libraries ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_CC+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_ac_ct_CC+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_CC+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_CC+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_CC+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_ac_ct_CC+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error "no acceptable C compiler found in \$PATH See \`config.log' for more details." "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 $as_echo_n "checking whether the C compiler works... " >&6; } ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # The possible output files: ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { { ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link_default") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an `-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else ac_file='' fi if test -z "$ac_file"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { as_fn_set_status 77 as_fn_error "C compiler cannot create executables See \`config.log' for more details." "$LINENO" 5; }; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 $as_echo_n "checking for C compiler default output file name... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 $as_echo "$ac_file" >&6; } ac_exeext=$ac_cv_exeext rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 $as_echo_n "checking for suffix of executables... " >&6; } if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error "cannot compute suffix of executables: cannot compile and link See \`config.log' for more details." "$LINENO" 5; } fi rm -f conftest conftest$ac_cv_exeext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 $as_echo "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { FILE *f = fopen ("conftest.out", "w"); return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF ac_clean_files="$ac_clean_files conftest.out" # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 $as_echo_n "checking whether we are cross compiling... " >&6; } if test "$cross_compiling" != yes; then { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if { ac_try='./conftest$ac_cv_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error "cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details." "$LINENO" 5; } fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 $as_echo "$cross_compiling" >&6; } rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 $as_echo_n "checking for suffix of object files... " >&6; } if test "${ac_cv_objext+set}" = set; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error "cannot compute suffix of object files: cannot compile See \`config.log' for more details." "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 $as_echo "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if test "${ac_cv_c_compiler_gnu+set}" = set; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if test "${ac_cv_prog_cc_g+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if test "${ac_cv_prog_cc_c89+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lc" >&5 $as_echo_n "checking for main in -lc... " >&6; } if test "${ac_cv_lib_c_main+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lc $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_c_main=yes else ac_cv_lib_c_main=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_c_main" >&5 $as_echo "$ac_cv_lib_c_main" >&6; } if test "x$ac_cv_lib_c_main" = x""yes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBC 1 _ACEOF LIBS="-lc $LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lpthread" >&5 $as_echo_n "checking for main in -lpthread... " >&6; } if test "${ac_cv_lib_pthread_main+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lpthread $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_pthread_main=yes else ac_cv_lib_pthread_main=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_main" >&5 $as_echo "$ac_cv_lib_pthread_main" >&6; } if test "x$ac_cv_lib_pthread_main" = x""yes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBPTHREAD 1 _ACEOF LIBS="-lpthread $LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lz" >&5 $as_echo_n "checking for main in -lz... " >&6; } if test "${ac_cv_lib_z_main+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lz $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_z_main=yes else ac_cv_lib_z_main=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_z_main" >&5 $as_echo "$ac_cv_lib_z_main" >&6; } if test "x$ac_cv_lib_z_main" = x""yes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBZ 1 _ACEOF LIBS="-lz $LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -llzo2" >&5 $as_echo_n "checking for main in -llzo2... " >&6; } if test "${ac_cv_lib_lzo2_main+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-llzo2 $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_lzo2_main=yes else ac_cv_lib_lzo2_main=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_lzo2_main" >&5 $as_echo "$ac_cv_lib_lzo2_main" >&6; } if test "x$ac_cv_lib_lzo2_main" = x""yes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBLZO2 1 _ACEOF LIBS="-llzo2 $LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lbz2" >&5 $as_echo_n "checking for main in -lbz2... " >&6; } if test "${ac_cv_lib_bz2_main+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lbz2 $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_bz2_main=yes else ac_cv_lib_bz2_main=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_bz2_main" >&5 $as_echo "$ac_cv_lib_bz2_main" >&6; } if test "x$ac_cv_lib_bz2_main" = x""yes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBBZ2 1 _ACEOF LIBS="-lbz2 $LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -liconv" >&5 $as_echo_n "checking for main in -liconv... " >&6; } if test "${ac_cv_lib_iconv_main+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-liconv $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_iconv_main=yes else ac_cv_lib_iconv_main=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_iconv_main" >&5 $as_echo "$ac_cv_lib_iconv_main" >&6; } if test "x$ac_cv_lib_iconv_main" = x""yes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBICONV 1 _ACEOF LIBS="-liconv $LIBS" fi # Duplication of QDBM for Perl { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lqdbm" >&5 $as_echo_n "checking for main in -lqdbm... " >&6; } if test "${ac_cv_lib_qdbm_main+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lqdbm $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_qdbm_main=yes else ac_cv_lib_qdbm_main=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_qdbm_main" >&5 $as_echo "$ac_cv_lib_qdbm_main" >&6; } if test "x$ac_cv_lib_qdbm_main" = x""yes; then : true else printf 'checking whether /usr/local/lib/libqdbm.* is... ' if ls /usr/local/lib/libqdbm.* > /dev/null 2>&1 then printf 'yes\n' else printf 'no\n' printf '#================================================================\n' 1>&2 printf '# WARNING: Install QDBM libraries before installation.\n' 1>&2 printf '#================================================================\n' 1>&2 fi fi # Targets ac_config_files="$ac_config_files Makefile" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then test "x$cache_file" != "x/dev/null" && { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} cat confcache >$cache_file else { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' # Transform confdefs.h into DEFS. # Protect against shell expansion while executing Makefile rules. # Protect against Makefile macro expansion. # # If the first sed substitution is executed (which looks for macros that # take arguments), then branch to the quote section. Otherwise, # look for a macro that doesn't take arguments. ac_script=' :mline /\\$/{ N s,\\\n,, b mline } t clear :clear s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g t quote s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g t quote b any :quote s/[ `~#$^&*(){}\\|;'\''"<>?]/\\&/g s/\[/\\&/g s/\]/\\&/g s/\$/$$/g H :any ${ g s/^\n// s/\n/ /g p } ' DEFS=`sed -n "$ac_script" confdefs.h` ac_libobjs= ac_ltlibobjs= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`$as_echo "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs : ${CONFIG_STATUS=./config.status} ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 $as_echo "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # as_fn_error ERROR [LINENO LOG_FD] # --------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with status $?, using 1 if that was 0. as_fn_error () { as_status=$?; test $as_status -eq 0 && as_status=1 if test "$3"; then as_lineno=${as_lineno-"$2"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $1" >&$3 fi $as_echo "$as_me: error: $1" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -p'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -p' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -p' fi else as_ln_s='cp -p' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi if test -x / >/dev/null 2>&1; then as_test_x='test -x' else if ls -dL / >/dev/null 2>&1; then as_ls_L_option=L else as_ls_L_option= fi as_test_x=' eval sh -c '\'' if test -d "$1"; then test -d "$1/."; else case $1 in #( -*)set "./$1";; esac; case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( ???[sx]*):;;*)false;;esac;fi '\'' sh ' fi as_executable_p=$as_test_x # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 ## ----------------------------------- ## ## Main body of $CONFIG_STATUS script. ## ## ----------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by qdbm-perl $as_me 1.0.0, which was generated by GNU Autoconf 2.65. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ \`$as_me' instantiates files and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit --config print configuration, then exit -q, --quiet, --silent do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE Configuration files: $config_files Report bugs to the package provider." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ qdbm-perl config.status 1.0.0 configured by $0, generated by GNU Autoconf 2.65, with options \\"\$ac_cs_config\\" Copyright (C) 2009 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) $as_echo "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) $as_echo "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --he | --h | --help | --hel | -h ) $as_echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) as_fn_error "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX $as_echo "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; *) as_fn_error "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= trap 'exit_status=$? { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error "cannot create a temporary directory in ." "$LINENO" 5 # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with `./config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=`echo X | tr X '\015'` # On cygwin, bash can eat \r inside `` if the user requested igncr. # But we know of no other shell where ac_cr would be empty at this # point, so we can use a bashism as a fallback. if test "x$ac_cr" = x; then eval ac_cr=\$\'\\r\' fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_num=`echo "$ac_subst_vars" | grep -c '$'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>"\$tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\)..*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\)..*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' >$CONFIG_STATUS || ac_write_fail=1 rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$tmp/subs1.awk" > "$tmp/subs.awk" \ || as_fn_error "could not setup config files machinery" "$LINENO" 5 _ACEOF # VPATH may cause trouble with some makes, so we remove $(srcdir), # ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=/{ s/:*\$(srcdir):*/:/ s/:*\${srcdir}:*/:/ s/:*@srcdir@:*/:/ s/^\([^=]*=[ ]*\):*/\1/ s/:*$// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" eval set X " :F $CONFIG_FILES " shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) as_fn_error "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || as_fn_error "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 $as_echo "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`$as_echo "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$tmp/stdin" \ || as_fn_error "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 $as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$tmp/subs.awk" >$tmp/out \ || as_fn_error "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } && { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined." >&5 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined." >&2;} rm -f "$tmp/stdin" case $ac_file in -) cat "$tmp/out" && rm -f "$tmp/out";; *) rm -f "$ac_file" && mv "$tmp/out" "$ac_file";; esac \ || as_fn_error "could not create $ac_file" "$LINENO" 5 ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || as_fn_error "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit $? fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi # END OF FILE qdbm-1.8.78/perl/plspex-ja.html0000644000175000017500000002567011426311535015312 0ustar mikiomikio Specifications of QDBM for Perl (Japanese)

QDBM付属Perl用API仕様書

Copyright (C) 2000-2006 Mikio Hirabayashi
Last Update: Thu, 26 Oct 2006 15:00:20 +0900

目次

  1. 概è¦
  2. インストール
  3. サンプルコード
  4. ãƒã‚°

概è¦

QDBMã«ã¯Perl言語用ã®APIãŒã‚る。QDBMã®åŸºæœ¬APIã¨æ‹¡å¼µAPIã¨ä¸Šç´šAPIã®é–¢æ•°ç¾¤ã‚’Perlã®ã‚¯ãƒ©ã‚¹æ©Ÿæ§‹ã‚’用ã„ã¦ã‚«ãƒ—セル化ã—ãŸã‚‚ã®ã§ã‚る。C言語ã®APIã‚’XS言語を介ã—ã¦å‘¼ã³å‡ºã™ã‚ˆã†ã«å®Ÿè£…ã•れã¦ã„る。データベースを扱ã†ã«ã¯ã€ãƒ¡ã‚½ãƒƒãƒ‰ã‚’明示的ã«å‘¼ã³å‡ºã™æ–¹æ³•ã¨ã€ãƒãƒƒã‚·ãƒ¥ã«ã‚¿ã‚¤ã™ã‚‹æ–¹æ³•ãŒã‚る。

メソッドを明示的ã«åˆ©ç”¨ã™ã‚‹å ´åˆã€ã‚¯ãƒ©ã‚¹ `Depot' ã‹ `Curia' ã‹ `Villa' ã®ã‚³ãƒ³ã‚¹ãƒˆãƒ©ã‚¯ã‚¿ `new' を呼ã³å‡ºã—ã¦ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’é–‹ãã€ãã®æˆ»ã‚Šå€¤ã®ã‚ªãƒ–ジェクトをãƒãƒ³ãƒ‰ãƒ«ã«ã™ã‚‹ã€‚データベースを閉ã˜ã‚‹ã«ã¯ãƒ¡ã‚½ãƒƒãƒ‰ `close' を呼ã¶ã€‚明示的ã«ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’é–‰ã˜ãªã„ã§ã‚¤ãƒ³ã‚¹ã‚¿ãƒ³ã‚¹ãŒç ´æ£„ã•れる場åˆã¯ã€ãƒ‡ã‚¹ãƒˆãƒ©ã‚¯ã‚¿ã«ã‚ˆã£ã¦ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãŒé–‰ã˜ã‚‰ã‚Œã‚‹ã€‚メソッド `put' ã¯ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’追加ã™ã‚‹ãŸã‚ã«ç”¨ã„る。メソッド `out' ã¯ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’削除ã™ã‚‹ãŸã‚ã«ç”¨ã„る。メソッド `get' ã¯ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’検索ã™ã‚‹ãŸã‚ã«ç”¨ã„る。ãã®ä»–ã«ã‚‚ã€C言語ã®APIã¨ã»ã¼åŒã˜æ“作を利用ã™ã‚‹ã“ã¨ãŒã§ãる。

ãƒãƒƒã‚·ãƒ¥ã«ã‚¿ã‚¤ã™ã‚‹å ´åˆã€`tie' 関数ã®ç¬¬ä¸‰å¼•数以é™ã«ã‚³ãƒ³ã‚¹ãƒˆãƒ©ã‚¯ã‚¿ã¨åŒæ§˜ã®å¼•数を与ãˆã‚‹ã€‚タイã—ãŸä»¥å¾Œã¯ãã®ãƒãƒƒã‚·ãƒ¥ã«å¯¾ã™ã‚‹æ“作ã¯ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã¸ã®æ“作ã¨ã¿ãªã•れる。データベースを閉ã˜ã‚‹ã«ã¯ `untie' 関数を用ã„る。

ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«æ ¼ç´ã™ã‚‹ãƒ¬ã‚³ãƒ¼ãƒ‰ã®ã‚­ãƒ¼ã¨å€¤ã¯æ–‡å­—列ã¨ã—ã¦æ‰±ã‚れるãŒã€ãƒã‚¤ãƒŠãƒªãƒ‡ãƒ¼ã‚¿ã‚’ãã®ã¾ã¾æ ¼ç´ã™ã‚‹ã“ã¨ã‚‚å¯èƒ½ã§ã‚る。`Depot' ã¯ãƒ•ァイルを用ã„ã¦ãƒãƒƒã‚·ãƒ¥ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’実ç¾ã—ã€`Curia' ã¯ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã¨è¤‡æ•°ã®ãƒ•ァイルを用ã„ã¦ãƒãƒƒã‚·ãƒ¥ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’実ç¾ã—ã€`Villa' ã¯ãƒ•ァイルを用ã„ã¦B+木データベースを実ç¾ã™ã‚‹ã€‚`Depot' ã¯æœ€ã‚‚高速ã§ã‚る。`Curia' ã¯æœ€ã‚‚スケーラブルã§ã‚る。`Villa' ã¯ã‚«ãƒ¼ã‚½ãƒ«ã«ã‚ˆã£ã¦é †åºã«åŸºã¥ãå‚ç…§ã‚’å¯èƒ½ã«ã™ã‚‹ã€‚

APIã®è©³ç´°ã«é–¢ã—ã¦ã¯ã€ã‚µãƒ–ディレクトリ `plapidoc' ã®æ–‡æ›¸ã‚’å‚ç…§ã™ã‚‹ã“ã¨ã€‚


インストール

Perlã®5.6.0以é™ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ãŒã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•れã€QDBM㌠`/usr/local' 以下ã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•れã¦ã„ã‚‹ã“ã¨ãŒå¿…è¦ã§ã‚る。

インストール作業ã¯ã€ã‚µãƒ–ディレクトリ `perl' をカレントディレクトリã«ã—ã¦è¡Œã†ã€‚

cd perl

ビルド環境を設定ã™ã‚‹ã€‚

./configure

プログラムをビルドã™ã‚‹ã€‚

make

プログラムã®è‡ªå·±è¨ºæ–­ãƒ†ã‚¹ãƒˆã‚’行ã†ã€‚

make check

プログラムをインストールã™ã‚‹ã€‚作業㯠`root' ユーザã§è¡Œã†ã€‚

make install

一連ã®ä½œæ¥­ãŒçµ‚ã‚‹ã¨ã€Perlã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã«å¿œã˜ãŸé©å½“ãªå ´æ‰€ã« `Depot.so'ã€`Depot.pm' ã€`Curia.so' ã€`Curia.pm' ã€`Villa.so' ã€`Villa.pm' ç­‰ã®ãƒ©ã‚¤ãƒ–ラリãŒã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•れã€ã‚³ãƒžãƒ³ãƒ‰ `pldptest' 㨠`plcrtest' 㨠`plvltest' ㌠`/usr/local/bin' ã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•れる。

アンインストールã™ã‚‹ã«ã¯ã€`./configure' ã‚’ã—ãŸå¾Œã®çŠ¶æ…‹ã§ä»¥ä¸‹ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹ã€‚作業㯠`root' ユーザã§è¡Œã†ã€‚

make uninstall

サンプルコード

åå‰ã¨å¯¾å¿œã•ã›ã¦é›»è©±ç•ªå·ã‚’æ ¼ç´ã—ã€ãれを検索ã™ã‚‹ã‚¢ãƒ—リケーションã®ã‚µãƒ³ãƒ—ルコードを以下ã«ç¤ºã™ã€‚

use Depot;

use constant NAME => "mikio";
use constant NUMBER => "000-1234-5678";
use constant DBNAME => "book";

sub main {
    my($depot, $val);

    # データベースを開ã
    if(!($depot = new Depot(&DBNAME, Depot::OWRITER | Depot::OCREAT))){
        printf(STDERR "new failed: %s\n", $Depot::errmsg);
        return 1;
    }

    # レコードを格ç´ã™ã‚‹
    if(!$depot->put(&NAME, &NUMBER)){
        printf(STDERR "put failed: %s\n", $Depot::errmsg);
    }

    # レコードをå–å¾—ã™ã‚‹
    if(!($val = $depot->get(&NAME))){
        printf(STDERR "get failed: %s\n", $Depot::errmsg);
    } else {
        printf("Name: %s\n", &NAME);
        printf("Number: %s\n", $val);
    }

    # データベースを閉ã˜ã‚‹
    if(!$depot->close()){
        printf(STDERR "close failed: %s\n", $Depot::errmsg);
        return 1;
    }

    return 0;
}

exit(main());

上記ã®ä¾‹ã‚’タイ関数を用ã„ã¦æ›¸ãç›´ã—ãŸä¾‹ã‚’以下ã«ç¤ºã™ã€‚

use Depot;

use constant NAME => "mikio";
use constant NUMBER => "000-1234-5678";
use constant DBNAME => "book";

sub main {
    my(%hash, $val);

    # データベースを開ã
    if(!tie(%hash, "Depot", &DBNAME, Depot::OWRITER | Depot::OCREAT)){
        printf(STDERR "tie failed: %s\n", $Depot::errmsg);
        return 1;
    }

    # レコードを格ç´ã™ã‚‹
    if(!($hash{&NAME} = &NUMBER)){
        printf(STDERR "store failed: %s\n", $Depot::errmsg);
    }

    # レコードをå–å¾—ã™ã‚‹
    if(!($val = $hash{&NAME})){
        printf(STDERR "fetch failed: %s\n", $Depot::errmsg);
    } else {
        printf("Name: %s\n", &NAME);
        printf("Number: %s\n", $val);
    }

    # データベースを閉ã˜ã‚‹
    if(!untie(%hash)){
        printf(STDERR "untie failed: %s\n", $Depot::errmsg);
        return 1;
    }

    return 0;
}

exit(main());

`Villa' クラスを用ã„ã¦æ–‡å­—列ã®å‰æ–¹ä¸€è‡´æ¤œç´¢ã‚’行ã†ä¾‹ã‚’以下ã«ç¤ºã™ã€‚

use Villa;

use constant DBNAME => "words";
use constant PREFIX => "apple";

sub main {
    my($villa, $key, $val);

    # データベースを開ã
    if(!($villa = new Villa(&DBNAME, Villa::OWRITER | Villa::OCREAT))){
        printf(STDERR "new failed: %s\n", $Villa::errmsg);
        return 1;
    }

    # レコードを格ç´ã™ã‚‹
    if(!$villa->put("applet", "little application", Villa::DDUP) ||
       !$villa->put("aurora", "polar wonderwork", Villa::DDUP) ||
       !$villa->put("apple", "delicious fruit", Villa::DDUP) ||
       !$villa->put("amigo", "good friend", Villa::DDUP) ||
       !$villa->put("apple", "big city", Villa::DDUP)){
        printf(STDERR "put failed: %s\n", $Villa::errmsg);
    }

    # カーソルを候補ã®å…ˆé ­ã«ç½®ã
    $villa->curjump(&PREFIX);

    # カーソルを走査ã™ã‚‹
    while($key = $villa->curkey()){
        my($prefix) = &PREFIX;
        ($key =~ m/^$prefix/) || last;
        $val = $villa->curval();
        printf("%s: %s\n", $key, $val);
        $villa->curnext();
    }

    # データベースを閉ã˜ã‚‹
    if(!$villa->close()){
        printf(STDERR "close failed: %s\n", $Villa::errmsg);
        return 1;
    }

    return 0;
}

exit(main());

ãƒã‚°

今ã®ã¨ã“ã‚ã€AnyDBM_Fileã®ä»²é–“ã§ã¯ãªã„。

ã‚‚ã—ã‚‚Perlãƒãƒƒã‚«ãƒ¼é”ã®æ‰‹ã«ã‹ã‹ã‚Œã°ã€ã‚ˆã‚ŠåŠ¹çŽ‡çš„ãªå®Ÿè£…ãŒãªã•れるã ã‚ã†ã€‚

インタフェースを簡潔ã«ã™ã‚‹ãŸã‚ã€Perl用ã®Curiaã«ã¯ãƒ©ãƒ¼ã‚¸ã‚ªãƒ–ã‚¸ã‚§ã‚¯ãƒˆã‚’æ‰±ã†æ©Ÿèƒ½ãŒãªãã€Perl用ã®Villaã®æ¯”較関数ã«ã¯ãƒ¦ãƒ¼ã‚¶å®šç¾©é–¢æ•°ã‚’指定ã§ããªã„。


qdbm-1.8.78/curia.h0000644000175000017500000005534010573416530013033 0ustar mikiomikio/************************************************************************************************* * The extended API of QDBM * Copyright (C) 2000-2007 Mikio Hirabayashi * This file is part of QDBM, Quick Database Manager. * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU * Lesser General Public License as published by the Free Software Foundation; either version * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * You should have received a copy of the GNU Lesser General Public License along with QDBM; if * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. *************************************************************************************************/ #ifndef _CURIA_H /* duplication check */ #define _CURIA_H #if defined(__cplusplus) /* export for C++ */ extern "C" { #endif #include #include #include #if defined(_MSC_VER) && !defined(QDBM_INTERNAL) && !defined(QDBM_STATIC) #define MYEXTERN extern __declspec(dllimport) #else #define MYEXTERN extern #endif /************************************************************************************************* * API *************************************************************************************************/ typedef struct { /* type of structure for the database handle */ char *name; /* name of the database directory */ int wmode; /* whether to be writable */ int inode; /* inode of the database directory */ DEPOT *attr; /* database handle for attributes */ DEPOT **depots; /* handles of the record database */ int dnum; /* number of record database handles */ int inum; /* number of the database of the using iterator */ int lrnum; /* number of large objects */ } CURIA; enum { /* enumeration for open modes */ CR_OREADER = 1 << 0, /* open as a reader */ CR_OWRITER = 1 << 1, /* open as a writer */ CR_OCREAT = 1 << 2, /* a writer creating */ CR_OTRUNC = 1 << 3, /* a writer truncating */ CR_ONOLCK = 1 << 4, /* open without locking */ CR_OLCKNB = 1 << 5, /* lock without blocking */ CR_OSPARSE = 1 << 6 /* create as sparse files */ }; enum { /* enumeration for write modes */ CR_DOVER, /* overwrite an existing value */ CR_DKEEP, /* keep an existing value */ CR_DCAT /* concatenate values */ }; /* Get a database handle. `name' specifies the name of a database directory. `omode' specifies the connection mode: `CR_OWRITER' as a writer, `CR_OREADER' as a reader. If the mode is `CR_OWRITER', the following may be added by bitwise or: `CR_OCREAT', which means it creates a new database if not exist, `CR_OTRUNC', which means it creates a new database regardless if one exists. Both of `CR_OREADER' and `CR_OWRITER' can be added to by bitwise or: `CR_ONOLCK', which means it opens a database directory without file locking, or `CR_OLCKNB', which means locking is performed without blocking. `CR_OCREAT' can be added to by bitwise or: `CR_OSPARSE', which means it creates database files as sparse files. `bnum' specifies the number of elements of each bucket array. If it is not more than 0, the default value is specified. The size of each bucket array is determined on creating, and can not be changed except for by optimization of the database. Suggested size of each bucket array is about from 0.5 to 4 times of the number of all records to store. `dnum' specifies the number of division of the database. If it is not more than 0, the default value is specified. The number of division can not be changed from the initial value. The max number of division is 512. The return value is the database handle or `NULL' if it is not successful. While connecting as a writer, an exclusive lock is invoked to the database directory. While connecting as a reader, a shared lock is invoked to the database directory. The thread blocks until the lock is achieved. If `CR_ONOLCK' is used, the application is responsible for exclusion control. */ CURIA *cropen(const char *name, int omode, int bnum, int dnum); /* Close a database handle. `curia' specifies a database handle. If successful, the return value is true, else, it is false. Because the region of a closed handle is released, it becomes impossible to use the handle. Updating a database is assured to be written when the handle is closed. If a writer opens a database but does not close it appropriately, the database will be broken. */ int crclose(CURIA *curia); /* Store a record. `curia' specifies a database handle connected as a writer. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `vbuf' specifies the pointer to the region of a value. `vsiz' specifies the size of the region of the value. If it is negative, the size is assigned with `strlen(vbuf)'. `dmode' specifies behavior when the key overlaps, by the following values: `CR_DOVER', which means the specified value overwrites the existing one, `CR_DKEEP', which means the existing value is kept, `CR_DCAT', which means the specified value is concatenated at the end of the existing value. If successful, the return value is true, else, it is false. */ int crput(CURIA *curia, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int dmode); /* Delete a record. `curia' specifies a database handle connected as a writer. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. If successful, the return value is true, else, it is false. False is returned when no record corresponds to the specified key. */ int crout(CURIA *curia, const char *kbuf, int ksiz); /* Retrieve a record. `curia' specifies a database handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `start' specifies the offset address of the beginning of the region of the value to be read. `max' specifies the max size to be read. If it is negative, the size to read is unlimited. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the region of the value of the corresponding record, else, it is `NULL'. `NULL' is returned when no record corresponds to the specified key or the size of the value of the corresponding record is less than `start'. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. */ char *crget(CURIA *curia, const char *kbuf, int ksiz, int start, int max, int *sp); /* Retrieve a record and write the value into a buffer. `curia' specifies a database handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `start' specifies the offset address of the beginning of the region of the value to be read. `max' specifies the max size to be read. It shuld be equal to or less than the size of the writing buffer. `vbuf' specifies the pointer to a buffer into which the value of the corresponding record is written. If successful, the return value is the size of the written data, else, it is -1. -1 is returned when no record corresponds to the specified key or the size of the value of the corresponding record is less than `start'. Note that no additional zero code is appended at the end of the region of the writing buffer. */ int crgetwb(CURIA *curia, const char *kbuf, int ksiz, int start, int max, char *vbuf); /* Get the size of the value of a record. `curia' specifies a database handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. If successful, the return value is the size of the value of the corresponding record, else, it is -1. Because this function does not read the entity of a record, it is faster than `crget'. */ int crvsiz(CURIA *curia, const char *kbuf, int ksiz); /* Initialize the iterator of a database handle. `curia' specifies a database handle. If successful, the return value is true, else, it is false. The iterator is used in order to access the key of every record stored in a database. */ int criterinit(CURIA *curia); /* Get the next key of the iterator. `curia' specifies a database handle. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the region of the next key, else, it is `NULL'. `NULL' is returned when no record is to be get out of the iterator. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. It is possible to access every record by iteration of calling this function. However, it is not assured if updating the database is occurred while the iteration. Besides, the order of this traversal access method is arbitrary, so it is not assured that the order of storing matches the one of the traversal access. */ char *criternext(CURIA *curia, int *sp); /* Set alignment of a database handle. `curia' specifies a database handle connected as a writer. `align' specifies the size of alignment. If successful, the return value is true, else, it is false. If alignment is set to a database, the efficiency of overwriting values is improved. The size of alignment is suggested to be average size of the values of the records to be stored. If alignment is positive, padding whose size is multiple number of the alignment is placed. If alignment is negative, as `vsiz' is the size of a value, the size of padding is calculated with `(vsiz / pow(2, abs(align) - 1))'. Because alignment setting is not saved in a database, you should specify alignment every opening a database. */ int crsetalign(CURIA *curia, int align); /* Set the size of the free block pool of a database handle. `curia' specifies a database handle connected as a writer. `size' specifies the size of the free block pool of a database. If successful, the return value is true, else, it is false. The default size of the free block pool is 16. If the size is greater, the space efficiency of overwriting values is improved with the time efficiency sacrificed. */ int crsetfbpsiz(CURIA *curia, int size); /* Synchronize updating contents with the files and the devices. `curia' specifies a database handle connected as a writer. If successful, the return value is true, else, it is false. This function is useful when another process uses the connected database directory. */ int crsync(CURIA *curia); /* Optimize a database. `curia' specifies a database handle connected as a writer. `bnum' specifies the number of the elements of each bucket array. If it is not more than 0, the default value is specified. If successful, the return value is true, else, it is false. In an alternating succession of deleting and storing with overwrite or concatenate, dispensable regions accumulate. This function is useful to do away with them. */ int croptimize(CURIA *curia, int bnum); /* Get the name of a database. `curia' specifies a database handle. If successful, the return value is the pointer to the region of the name of the database, else, it is `NULL'. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. */ char *crname(CURIA *curia); /* Get the total size of database files. `curia' specifies a database handle. If successful, the return value is the total size of the database files, else, it is -1. If the total size is more than 2GB, the return value overflows. */ int crfsiz(CURIA *curia); /* Get the total size of database files as double-precision floating-point number. `curia' specifies a database handle. If successful, the return value is the total size of the database files, else, it is -1.0. */ double crfsizd(CURIA *curia); /* Get the total number of the elements of each bucket array. `curia' specifies a database handle. If successful, the return value is the total number of the elements of each bucket array, else, it is -1. */ int crbnum(CURIA *curia); /* Get the total number of the used elements of each bucket array. `curia' specifies a database handle. If successful, the return value is the total number of the used elements of each bucket array, else, it is -1. This function is inefficient because it accesses all elements of each bucket array. */ int crbusenum(CURIA *curia); /* Get the number of the records stored in a database. `curia' specifies a database handle. If successful, the return value is the number of the records stored in the database, else, it is -1. */ int crrnum(CURIA *curia); /* Check whether a database handle is a writer or not. `curia' specifies a database handle. The return value is true if the handle is a writer, false if not. */ int crwritable(CURIA *curia); /* Check whether a database has a fatal error or not. `curia' specifies a database handle. The return value is true if the database has a fatal error, false if not. */ int crfatalerror(CURIA *curia); /* Get the inode number of a database directory. `curia' specifies a database handle. The return value is the inode number of the database directory. */ int crinode(CURIA *curia); /* Get the last modified time of a database. `curia' specifies a database handle. The return value is the last modified time of the database. */ time_t crmtime(CURIA *curia); /* Remove a database directory. `name' specifies the name of a database directory. If successful, the return value is true, else, it is false. */ int crremove(const char *name); /* Repair a broken database directory. `name' specifies the name of a database directory. If successful, the return value is true, else, it is false. There is no guarantee that all records in a repaired database directory correspond to the original or expected state. */ int crrepair(const char *name); /* Dump all records as endian independent data. `curia' specifies a database handle. `name' specifies the name of an output directory. If successful, the return value is true, else, it is false. Note that large objects are ignored. */ int crexportdb(CURIA *curia, const char *name); /* Load all records from endian independent data. `curia' specifies a database handle connected as a writer. The database of the handle must be empty. `name' specifies the name of an input directory. If successful, the return value is true, else, it is false. Note that large objects are ignored. */ int crimportdb(CURIA *curia, const char *name); /* Retrieve a record directly from a database directory. `name' specifies the name of a database directory. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the region of the value of the corresponding record, else, it is `NULL'. `NULL' is returned when no record corresponds to the specified key. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. Although this function can be used even while the database directory is locked by another process, it is not assured that recent updated is reflected. */ char *crsnaffle(const char *name, const char *kbuf, int ksiz, int *sp); /* Store a large object. `curia' specifies a database handle connected as a writer. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `vbuf' specifies the pointer to the region of a value. `vsiz' specifies the size of the region of the value. If it is negative, the size is assigned with `strlen(vbuf)'. `dmode' specifies behavior when the key overlaps, by the following values: `CR_DOVER', which means the specified value overwrites the existing one, `CR_DKEEP', which means the existing value is kept, `CR_DCAT', which means the specified value is concatenated at the end of the existing value. If successful, the return value is true, else, it is false. */ int crputlob(CURIA *curia, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int dmode); /* Delete a large object. `curia' specifies a database handle connected as a writer. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. If successful, the return value is true, else, it is false. false is returned when no large object corresponds to the specified key. */ int croutlob(CURIA *curia, const char *kbuf, int ksiz); /* Retrieve a large object. `curia' specifies a database handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `start' specifies the offset address of the beginning of the region of the value to be read. `max' specifies the max size to be read. If it is negative, the size to read is unlimited. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the region of the value of the corresponding large object, else, it is `NULL'. `NULL' is returned when no large object corresponds to the specified key or the size of the value of the corresponding large object is less than `start'. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. */ char *crgetlob(CURIA *curia, const char *kbuf, int ksiz, int start, int max, int *sp); /* Get the file descriptor of a large object. `curia' specifies a database handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. If successful, the return value is the file descriptor of the corresponding large object, else, it is -1. -1 is returned when no large object corresponds to the specified key. The returned file descriptor is opened with the `open' call. If the database handle was opened as a writer, the descriptor is writable (O_RDWR), else, it is not writable (O_RDONLY). The descriptor should be closed with the `close' call if it is no longer in use. */ int crgetlobfd(CURIA *curia, const char *kbuf, int ksiz); /* Get the size of the value of a large object. `curia' specifies a database handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. If successful, the return value is the size of the value of the corresponding large object, else, it is -1. Because this function does not read the entity of a large object, it is faster than `crgetlob'. */ int crvsizlob(CURIA *curia, const char *kbuf, int ksiz); /* Get the number of the large objects stored in a database. `curia' specifies a database handle. If successful, the return value is the number of the large objects stored in the database, else, it is -1. */ int crrnumlob(CURIA *curia); /************************************************************************************************* * features for experts *************************************************************************************************/ /* Synchronize updating contents on memory. `curia' specifies a database handle connected as a writer. If successful, the return value is true, else, it is false. */ int crmemsync(CURIA *curia); /* Synchronize updating contents on memory, not physically. `curia' specifies a database handle connected as a writer. If successful, the return value is true, else, it is false. */ int crmemflush(CURIA *curia); /* Get flags of a database. `curia' specifies a database handle. The return value is the flags of a database. */ int crgetflags(CURIA *curia); /* Set flags of a database. `curia' specifies a database handle connected as a writer. `flags' specifies flags to set. Least ten bits are reserved for internal use. If successful, the return value is true, else, it is false. */ int crsetflags(CURIA *curia, int flags); #undef MYEXTERN #if defined(__cplusplus) /* export for C++ */ } #endif #endif /* duplication check */ /* END OF FILE */ qdbm-1.8.78/depot.c0000644000175000017500000020444410651144342013033 0ustar mikiomikio/************************************************************************************************* * Implementation of Depot * Copyright (C) 2000-2007 Mikio Hirabayashi * This file is part of QDBM, Quick Database Manager. * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU * Lesser General Public License as published by the Free Software Foundation; either version * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * You should have received a copy of the GNU Lesser General Public License along with QDBM; if * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. *************************************************************************************************/ #define QDBM_INTERNAL 1 #include "depot.h" #include "myconf.h" #define DP_FILEMODE 00644 /* permission of a creating file */ #define DP_MAGICNUMB "[DEPOT]\n\f" /* magic number on environments of big endian */ #define DP_MAGICNUML "[depot]\n\f" /* magic number on environments of little endian */ #define DP_HEADSIZ 48 /* size of the reagion of the header */ #define DP_LIBVEROFF 12 /* offset of the region for the library version */ #define DP_FLAGSOFF 16 /* offset of the region for flags */ #define DP_FSIZOFF 24 /* offset of the region for the file size */ #define DP_BNUMOFF 32 /* offset of the region for the bucket number */ #define DP_RNUMOFF 40 /* offset of the region for the record number */ #define DP_DEFBNUM 8191 /* default bucket number */ #define DP_FBPOOLSIZ 16 /* size of free block pool */ #define DP_ENTBUFSIZ 128 /* size of the entity buffer */ #define DP_STKBUFSIZ 256 /* size of the stack key buffer */ #define DP_WRTBUFSIZ 8192 /* size of the writing buffer */ #define DP_FSBLKSIZ 4096 /* size of a block of the file system */ #define DP_TMPFSUF MYEXTSTR "dptmp" /* suffix of a temporary file */ #define DP_OPTBLOAD 0.25 /* ratio of bucket loading at optimization */ #define DP_OPTRUNIT 256 /* number of records in a process of optimization */ #define DP_NUMBUFSIZ 32 /* size of a buffer for a number */ #define DP_IOBUFSIZ 8192 /* size of an I/O buffer */ /* get the first hash value */ #define DP_FIRSTHASH(DP_res, DP_kbuf, DP_ksiz) \ do { \ const unsigned char *_DP_p; \ int _DP_ksiz; \ _DP_p = (const unsigned char *)(DP_kbuf); \ _DP_ksiz = DP_ksiz; \ if((_DP_ksiz) == sizeof(int)){ \ memcpy(&(DP_res), (DP_kbuf), sizeof(int)); \ } else { \ (DP_res) = 751; \ } \ while(_DP_ksiz--){ \ (DP_res) = (DP_res) * 31 + *(_DP_p)++; \ } \ (DP_res) = ((DP_res) * 87767623) & INT_MAX; \ } while(FALSE) /* get the second hash value */ #define DP_SECONDHASH(DP_res, DP_kbuf, DP_ksiz) \ do { \ const unsigned char *_DP_p; \ int _DP_ksiz; \ _DP_p = (const unsigned char *)(DP_kbuf) + DP_ksiz - 1; \ _DP_ksiz = DP_ksiz; \ for((DP_res) = 19780211; _DP_ksiz--;){ \ (DP_res) = (DP_res) * 37 + *(_DP_p)--; \ } \ (DP_res) = ((DP_res) * 43321879) & INT_MAX; \ } while(FALSE) /* get the third hash value */ #define DP_THIRDHASH(DP_res, DP_kbuf, DP_ksiz) \ do { \ int _DP_i; \ (DP_res) = 774831917; \ for(_DP_i = (DP_ksiz) - 1; _DP_i >= 0; _DP_i--){ \ (DP_res) = (DP_res) * 29 + ((const unsigned char *)(DP_kbuf))[_DP_i]; \ } \ (DP_res) = ((DP_res) * 5157883) & INT_MAX; \ } while(FALSE) enum { /* enumeration for a record header */ DP_RHIFLAGS, /* offset of flags */ DP_RHIHASH, /* offset of value of the second hash function */ DP_RHIKSIZ, /* offset of the size of the key */ DP_RHIVSIZ, /* offset of the size of the value */ DP_RHIPSIZ, /* offset of the size of the padding bytes */ DP_RHILEFT, /* offset of the offset of the left child */ DP_RHIRIGHT, /* offset of the offset of the right child */ DP_RHNUM /* number of elements of a header */ }; enum { /* enumeration for the flag of a record */ DP_RECFDEL = 1 << 0, /* deleted */ DP_RECFREUSE = 1 << 1 /* reusable */ }; /* private function prototypes */ static int dpbigendian(void); static char *dpstrdup(const char *str); static int dplock(int fd, int ex, int nb); static int dpwrite(int fd, const void *buf, int size); static int dpseekwrite(int fd, int off, const void *buf, int size); static int dpseekwritenum(int fd, int off, int num); static int dpread(int fd, void *buf, int size); static int dpseekread(int fd, int off, void *buf, int size); static int dpfcopy(int destfd, int destoff, int srcfd, int srcoff); static int dpgetprime(int num); static int dppadsize(DEPOT *depot, int ksiz, int vsiz); static int dprecsize(int *head); static int dprechead(DEPOT *depot, int off, int *head, char *ebuf, int *eep); static char *dpreckey(DEPOT *depot, int off, int *head); static char *dprecval(DEPOT *depot, int off, int *head, int start, int max); static int dprecvalwb(DEPOT *depot, int off, int *head, int start, int max, char *vbuf); static int dpkeycmp(const char *abuf, int asiz, const char *bbuf, int bsiz); static int dprecsearch(DEPOT *depot, const char *kbuf, int ksiz, int hash, int *bip, int *offp, int *entp, int *head, char *ebuf, int *eep, int delhit); static int dprecrewrite(DEPOT *depot, int off, int rsiz, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int hash, int left, int right); static int dprecappend(DEPOT *depot, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int hash, int left, int right); static int dprecover(DEPOT *depot, int off, int *head, const char *vbuf, int vsiz, int cat); static int dprecdelete(DEPOT *depot, int off, int *head, int reusable); static void dpfbpoolcoal(DEPOT *depot); static int dpfbpoolcmp(const void *a, const void *b); /************************************************************************************************* * public objects *************************************************************************************************/ /* String containing the version information. */ const char *dpversion = _QDBM_VERSION; /* Get a message string corresponding to an error code. */ const char *dperrmsg(int ecode){ switch(ecode){ case DP_ENOERR: return "no error"; case DP_EFATAL: return "with fatal error"; case DP_EMODE: return "invalid mode"; case DP_EBROKEN: return "broken database file"; case DP_EKEEP: return "existing record"; case DP_ENOITEM: return "no item found"; case DP_EALLOC: return "memory allocation error"; case DP_EMAP: return "memory mapping error"; case DP_EOPEN: return "open error"; case DP_ECLOSE: return "close error"; case DP_ETRUNC: return "trunc error"; case DP_ESYNC: return "sync error"; case DP_ESTAT: return "stat error"; case DP_ESEEK: return "seek error"; case DP_EREAD: return "read error"; case DP_EWRITE: return "write error"; case DP_ELOCK: return "lock error"; case DP_EUNLINK: return "unlink error"; case DP_EMKDIR: return "mkdir error"; case DP_ERMDIR: return "rmdir error"; case DP_EMISC: return "miscellaneous error"; } return "(invalid ecode)"; } /* Get a database handle. */ DEPOT *dpopen(const char *name, int omode, int bnum){ char hbuf[DP_HEADSIZ], *map, c, *tname; int i, mode, fd, inode, fsiz, rnum, msiz, *fbpool; struct stat sbuf; time_t mtime; DEPOT *depot; assert(name); mode = O_RDONLY; if(omode & DP_OWRITER){ mode = O_RDWR; if(omode & DP_OCREAT) mode |= O_CREAT; } if((fd = open(name, mode, DP_FILEMODE)) == -1){ dpecodeset(DP_EOPEN, __FILE__, __LINE__); return NULL; } if(!(omode & DP_ONOLCK)){ if(!dplock(fd, omode & DP_OWRITER, omode & DP_OLCKNB)){ close(fd); return NULL; } } if((omode & DP_OWRITER) && (omode & DP_OTRUNC)){ if(ftruncate(fd, 0) == -1){ close(fd); dpecodeset(DP_ETRUNC, __FILE__, __LINE__); return NULL; } } if(fstat(fd, &sbuf) == -1 || !S_ISREG(sbuf.st_mode) || (sbuf.st_ino == 0 && lstat(name, &sbuf) == -1)){ close(fd); dpecodeset(DP_ESTAT, __FILE__, __LINE__); return NULL; } inode = sbuf.st_ino; mtime = sbuf.st_mtime; fsiz = sbuf.st_size; if((omode & DP_OWRITER) && fsiz == 0){ memset(hbuf, 0, DP_HEADSIZ); if(dpbigendian()){ memcpy(hbuf, DP_MAGICNUMB, strlen(DP_MAGICNUMB)); } else { memcpy(hbuf, DP_MAGICNUML, strlen(DP_MAGICNUML)); } sprintf(hbuf + DP_LIBVEROFF, "%d", _QDBM_LIBVER / 100); bnum = bnum < 1 ? DP_DEFBNUM : bnum; bnum = dpgetprime(bnum); memcpy(hbuf + DP_BNUMOFF, &bnum, sizeof(int)); rnum = 0; memcpy(hbuf + DP_RNUMOFF, &rnum, sizeof(int)); fsiz = DP_HEADSIZ + bnum * sizeof(int); memcpy(hbuf + DP_FSIZOFF, &fsiz, sizeof(int)); if(!dpseekwrite(fd, 0, hbuf, DP_HEADSIZ)){ close(fd); return NULL; } if(omode & DP_OSPARSE){ c = 0; if(!dpseekwrite(fd, fsiz - 1, &c, 1)){ close(fd); return NULL; } } else { if(!(map = malloc(bnum * sizeof(int)))){ close(fd); dpecodeset(DP_EALLOC, __FILE__, __LINE__); return NULL; } memset(map, 0, bnum * sizeof(int)); if(!dpseekwrite(fd, DP_HEADSIZ, map, bnum * sizeof(int))){ free(map); close(fd); return NULL; } free(map); } } if(!dpseekread(fd, 0, hbuf, DP_HEADSIZ)){ close(fd); dpecodeset(DP_EBROKEN, __FILE__, __LINE__); return NULL; } if(!(omode & DP_ONOLCK) && ((dpbigendian() ? memcmp(hbuf, DP_MAGICNUMB, strlen(DP_MAGICNUMB)) != 0 : memcmp(hbuf, DP_MAGICNUML, strlen(DP_MAGICNUML)) != 0) || *((int *)(hbuf + DP_FSIZOFF)) != fsiz)){ close(fd); dpecodeset(DP_EBROKEN, __FILE__, __LINE__); return NULL; } bnum = *((int *)(hbuf + DP_BNUMOFF)); rnum = *((int *)(hbuf + DP_RNUMOFF)); if(bnum < 1 || rnum < 0 || fsiz < DP_HEADSIZ + bnum * sizeof(int)){ close(fd); dpecodeset(DP_EBROKEN, __FILE__, __LINE__); return NULL; } msiz = DP_HEADSIZ + bnum * sizeof(int); map = mmap(0, msiz, PROT_READ | ((mode & DP_OWRITER) ? PROT_WRITE : 0), MAP_SHARED, fd, 0); if(map == MAP_FAILED){ close(fd); dpecodeset(DP_EMAP, __FILE__, __LINE__); return NULL; } tname = NULL; fbpool = NULL; if(!(depot = malloc(sizeof(DEPOT))) || !(tname = dpstrdup(name)) || !(fbpool = malloc(DP_FBPOOLSIZ * 2 * sizeof(int)))){ free(fbpool); free(tname); free(depot); munmap(map, msiz); close(fd); dpecodeset(DP_EALLOC, __FILE__, __LINE__); return NULL; } depot->name = tname; depot->wmode = (mode & DP_OWRITER); depot->inode = inode; depot->mtime = mtime; depot->fd = fd; depot->fsiz = fsiz; depot->map = map; depot->msiz = msiz; depot->buckets = (int *)(map + DP_HEADSIZ); depot->bnum = bnum; depot->rnum = rnum; depot->fatal = FALSE; depot->ioff = 0; depot->fbpool = fbpool; for(i = 0; i < DP_FBPOOLSIZ * 2; i += 2){ depot->fbpool[i] = -1; depot->fbpool[i+1] = -1; } depot->fbpsiz = DP_FBPOOLSIZ * 2; depot->fbpinc = 0; depot->align = 0; return depot; } /* Close a database handle. */ int dpclose(DEPOT *depot){ int fatal, err; assert(depot); fatal = depot->fatal; err = FALSE; if(depot->wmode){ *((int *)(depot->map + DP_FSIZOFF)) = depot->fsiz; *((int *)(depot->map + DP_RNUMOFF)) = depot->rnum; } if(depot->map != MAP_FAILED){ if(munmap(depot->map, depot->msiz) == -1){ err = TRUE; dpecodeset(DP_EMAP, __FILE__, __LINE__); } } if(close(depot->fd) == -1){ err = TRUE; dpecodeset(DP_ECLOSE, __FILE__, __LINE__); } free(depot->fbpool); free(depot->name); free(depot); if(fatal){ dpecodeset(DP_EFATAL, __FILE__, __LINE__); return FALSE; } return err ? FALSE : TRUE; } /* Store a record. */ int dpput(DEPOT *depot, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int dmode){ int head[DP_RHNUM], next[DP_RHNUM]; int i, hash, bi, off, entoff, ee, newoff, rsiz, nsiz, fdel, mroff, mrsiz, mi, min; char ebuf[DP_ENTBUFSIZ], *tval, *swap; assert(depot && kbuf && vbuf); if(depot->fatal){ dpecodeset(DP_EFATAL, __FILE__, __LINE__); return FALSE; } if(!depot->wmode){ dpecodeset(DP_EMODE, __FILE__, __LINE__); return FALSE; } if(ksiz < 0) ksiz = strlen(kbuf); if(vsiz < 0) vsiz = strlen(vbuf); newoff = -1; DP_SECONDHASH(hash, kbuf, ksiz); switch(dprecsearch(depot, kbuf, ksiz, hash, &bi, &off, &entoff, head, ebuf, &ee, TRUE)){ case -1: depot->fatal = TRUE; return FALSE; case 0: fdel = head[DP_RHIFLAGS] & DP_RECFDEL; if(dmode == DP_DKEEP && !fdel){ dpecodeset(DP_EKEEP, __FILE__, __LINE__); return FALSE; } if(fdel){ head[DP_RHIPSIZ] += head[DP_RHIVSIZ]; head[DP_RHIVSIZ] = 0; } rsiz = dprecsize(head); nsiz = DP_RHNUM * sizeof(int) + ksiz + vsiz; if(dmode == DP_DCAT) nsiz += head[DP_RHIVSIZ]; if(off + rsiz >= depot->fsiz){ if(rsiz < nsiz){ head[DP_RHIPSIZ] += nsiz - rsiz; rsiz = nsiz; depot->fsiz = off + rsiz; } } else { while(nsiz > rsiz && off + rsiz < depot->fsiz){ if(!dprechead(depot, off + rsiz, next, NULL, NULL)) return FALSE; if(!(next[DP_RHIFLAGS] & DP_RECFREUSE)) break; head[DP_RHIPSIZ] += dprecsize(next); rsiz += dprecsize(next); } for(i = 0; i < depot->fbpsiz; i += 2){ if(depot->fbpool[i] >= off && depot->fbpool[i] < off + rsiz){ depot->fbpool[i] = -1; depot->fbpool[i+1] = -1; } } } if(nsiz <= rsiz){ if(!dprecover(depot, off, head, vbuf, vsiz, dmode == DP_DCAT)){ depot->fatal = TRUE; return FALSE; } } else { tval = NULL; if(dmode == DP_DCAT){ if(ee && DP_RHNUM * sizeof(int) + head[DP_RHIKSIZ] + head[DP_RHIVSIZ] <= DP_ENTBUFSIZ){ if(!(tval = malloc(head[DP_RHIVSIZ] + vsiz + 1))){ dpecodeset(DP_EALLOC, __FILE__, __LINE__); depot->fatal = TRUE; return FALSE; } memcpy(tval, ebuf + (DP_RHNUM * sizeof(int) + head[DP_RHIKSIZ]), head[DP_RHIVSIZ]); } else { if(!(tval = dprecval(depot, off, head, 0, -1))){ depot->fatal = TRUE; return FALSE; } if(!(swap = realloc(tval, head[DP_RHIVSIZ] + vsiz + 1))){ free(tval); dpecodeset(DP_EALLOC, __FILE__, __LINE__); depot->fatal = TRUE; return FALSE; } tval = swap; } memcpy(tval + head[DP_RHIVSIZ], vbuf, vsiz); vsiz += head[DP_RHIVSIZ]; vbuf = tval; } mi = -1; min = -1; for(i = 0; i < depot->fbpsiz; i += 2){ if(depot->fbpool[i+1] < nsiz) continue; if(mi == -1 || depot->fbpool[i+1] < min){ mi = i; min = depot->fbpool[i+1]; } } if(mi >= 0){ mroff = depot->fbpool[mi]; mrsiz = depot->fbpool[mi+1]; depot->fbpool[mi] = -1; depot->fbpool[mi+1] = -1; } else { mroff = -1; mrsiz = -1; } if(!dprecdelete(depot, off, head, TRUE)){ free(tval); depot->fatal = TRUE; return FALSE; } if(mroff > 0 && nsiz <= mrsiz){ if(!dprecrewrite(depot, mroff, mrsiz, kbuf, ksiz, vbuf, vsiz, hash, head[DP_RHILEFT], head[DP_RHIRIGHT])){ free(tval); depot->fatal = TRUE; return FALSE; } newoff = mroff; } else { if((newoff = dprecappend(depot, kbuf, ksiz, vbuf, vsiz, hash, head[DP_RHILEFT], head[DP_RHIRIGHT])) == -1){ free(tval); depot->fatal = TRUE; return FALSE; } } free(tval); } if(fdel) depot->rnum++; break; default: if((newoff = dprecappend(depot, kbuf, ksiz, vbuf, vsiz, hash, 0, 0)) == -1){ depot->fatal = TRUE; return FALSE; } depot->rnum++; break; } if(newoff > 0){ if(entoff > 0){ if(!dpseekwritenum(depot->fd, entoff, newoff)){ depot->fatal = TRUE; return FALSE; } } else { depot->buckets[bi] = newoff; } } return TRUE; } /* Delete a record. */ int dpout(DEPOT *depot, const char *kbuf, int ksiz){ int head[DP_RHNUM], hash, bi, off, entoff, ee; char ebuf[DP_ENTBUFSIZ]; assert(depot && kbuf); if(depot->fatal){ dpecodeset(DP_EFATAL, __FILE__, __LINE__); return FALSE; } if(!depot->wmode){ dpecodeset(DP_EMODE, __FILE__, __LINE__); return FALSE; } if(ksiz < 0) ksiz = strlen(kbuf); DP_SECONDHASH(hash, kbuf, ksiz); switch(dprecsearch(depot, kbuf, ksiz, hash, &bi, &off, &entoff, head, ebuf, &ee, FALSE)){ case -1: depot->fatal = TRUE; return FALSE; case 0: break; default: dpecodeset(DP_ENOITEM, __FILE__, __LINE__); return FALSE; } if(!dprecdelete(depot, off, head, FALSE)){ depot->fatal = TRUE; return FALSE; } depot->rnum--; return TRUE; } /* Retrieve a record. */ char *dpget(DEPOT *depot, const char *kbuf, int ksiz, int start, int max, int *sp){ int head[DP_RHNUM], hash, bi, off, entoff, ee, vsiz; char ebuf[DP_ENTBUFSIZ], *vbuf; assert(depot && kbuf && start >= 0); if(depot->fatal){ dpecodeset(DP_EFATAL, __FILE__, __LINE__); return NULL; } if(ksiz < 0) ksiz = strlen(kbuf); DP_SECONDHASH(hash, kbuf, ksiz); switch(dprecsearch(depot, kbuf, ksiz, hash, &bi, &off, &entoff, head, ebuf, &ee, FALSE)){ case -1: depot->fatal = TRUE; return NULL; case 0: break; default: dpecodeset(DP_ENOITEM, __FILE__, __LINE__); return NULL; } if(start > head[DP_RHIVSIZ]){ dpecodeset(DP_ENOITEM, __FILE__, __LINE__); return NULL; } if(ee && DP_RHNUM * sizeof(int) + head[DP_RHIKSIZ] + head[DP_RHIVSIZ] <= DP_ENTBUFSIZ){ head[DP_RHIVSIZ] -= start; if(max < 0){ vsiz = head[DP_RHIVSIZ]; } else { vsiz = max < head[DP_RHIVSIZ] ? max : head[DP_RHIVSIZ]; } if(!(vbuf = malloc(vsiz + 1))){ dpecodeset(DP_EALLOC, __FILE__, __LINE__); depot->fatal = TRUE; return NULL; } memcpy(vbuf, ebuf + (DP_RHNUM * sizeof(int) + head[DP_RHIKSIZ] + start), vsiz); vbuf[vsiz] = '\0'; } else { if(!(vbuf = dprecval(depot, off, head, start, max))){ depot->fatal = TRUE; return NULL; } } if(sp){ if(max < 0){ *sp = head[DP_RHIVSIZ]; } else { *sp = max < head[DP_RHIVSIZ] ? max : head[DP_RHIVSIZ]; } } return vbuf; } /* Retrieve a record and write the value into a buffer. */ int dpgetwb(DEPOT *depot, const char *kbuf, int ksiz, int start, int max, char *vbuf){ int head[DP_RHNUM], hash, bi, off, entoff, ee, vsiz; char ebuf[DP_ENTBUFSIZ]; assert(depot && kbuf && start >= 0 && max >= 0 && vbuf); if(depot->fatal){ dpecodeset(DP_EFATAL, __FILE__, __LINE__); return -1; } if(ksiz < 0) ksiz = strlen(kbuf); DP_SECONDHASH(hash, kbuf, ksiz); switch(dprecsearch(depot, kbuf, ksiz, hash, &bi, &off, &entoff, head, ebuf, &ee, FALSE)){ case -1: depot->fatal = TRUE; return -1; case 0: break; default: dpecodeset(DP_ENOITEM, __FILE__, __LINE__); return -1; } if(start > head[DP_RHIVSIZ]){ dpecodeset(DP_ENOITEM, __FILE__, __LINE__); return -1; } if(ee && DP_RHNUM * sizeof(int) + head[DP_RHIKSIZ] + head[DP_RHIVSIZ] <= DP_ENTBUFSIZ){ head[DP_RHIVSIZ] -= start; vsiz = max < head[DP_RHIVSIZ] ? max : head[DP_RHIVSIZ]; memcpy(vbuf, ebuf + (DP_RHNUM * sizeof(int) + head[DP_RHIKSIZ] + start), vsiz); } else { if((vsiz = dprecvalwb(depot, off, head, start, max, vbuf)) == -1){ depot->fatal = TRUE; return -1; } } return vsiz; } /* Get the size of the value of a record. */ int dpvsiz(DEPOT *depot, const char *kbuf, int ksiz){ int head[DP_RHNUM], hash, bi, off, entoff, ee; char ebuf[DP_ENTBUFSIZ]; assert(depot && kbuf); if(depot->fatal){ dpecodeset(DP_EFATAL, __FILE__, __LINE__); return -1; } if(ksiz < 0) ksiz = strlen(kbuf); DP_SECONDHASH(hash, kbuf, ksiz); switch(dprecsearch(depot, kbuf, ksiz, hash, &bi, &off, &entoff, head, ebuf, &ee, FALSE)){ case -1: depot->fatal = TRUE; return -1; case 0: break; default: dpecodeset(DP_ENOITEM, __FILE__, __LINE__); return -1; } return head[DP_RHIVSIZ]; } /* Initialize the iterator of a database handle. */ int dpiterinit(DEPOT *depot){ assert(depot); if(depot->fatal){ dpecodeset(DP_EFATAL, __FILE__, __LINE__); return FALSE; } depot->ioff = 0; return TRUE; } /* Get the next key of the iterator. */ char *dpiternext(DEPOT *depot, int *sp){ int off, head[DP_RHNUM], ee; char ebuf[DP_ENTBUFSIZ], *kbuf; assert(depot); if(depot->fatal){ dpecodeset(DP_EFATAL, __FILE__, __LINE__); return NULL; } off = DP_HEADSIZ + depot->bnum * sizeof(int); off = off > depot->ioff ? off : depot->ioff; while(off < depot->fsiz){ if(!dprechead(depot, off, head, ebuf, &ee)){ depot->fatal = TRUE; return NULL; } if(head[DP_RHIFLAGS] & DP_RECFDEL){ off += dprecsize(head); } else { if(ee && DP_RHNUM * sizeof(int) + head[DP_RHIKSIZ] <= DP_ENTBUFSIZ){ if(!(kbuf = malloc(head[DP_RHIKSIZ] + 1))){ dpecodeset(DP_EALLOC, __FILE__, __LINE__); depot->fatal = TRUE; return NULL; } memcpy(kbuf, ebuf + (DP_RHNUM * sizeof(int)), head[DP_RHIKSIZ]); kbuf[head[DP_RHIKSIZ]] = '\0'; } else { if(!(kbuf = dpreckey(depot, off, head))){ depot->fatal = TRUE; return NULL; } } depot->ioff = off + dprecsize(head); if(sp) *sp = head[DP_RHIKSIZ]; return kbuf; } } dpecodeset(DP_ENOITEM, __FILE__, __LINE__); return NULL; } /* Set alignment of a database handle. */ int dpsetalign(DEPOT *depot, int align){ assert(depot); if(depot->fatal){ dpecodeset(DP_EFATAL, __FILE__, __LINE__); return FALSE; } if(!depot->wmode){ dpecodeset(DP_EMODE, __FILE__, __LINE__); return FALSE; } depot->align = align; return TRUE; } /* Set the size of the free block pool of a database handle. */ int dpsetfbpsiz(DEPOT *depot, int size){ int *fbpool; int i; assert(depot && size >= 0); if(depot->fatal){ dpecodeset(DP_EFATAL, __FILE__, __LINE__); return FALSE; } if(!depot->wmode){ dpecodeset(DP_EMODE, __FILE__, __LINE__); return FALSE; } size *= 2; if(!(fbpool = realloc(depot->fbpool, size * sizeof(int) + 1))){ dpecodeset(DP_EALLOC, __FILE__, __LINE__); return FALSE; } for(i = 0; i < size; i += 2){ fbpool[i] = -1; fbpool[i+1] = -1; } depot->fbpool = fbpool; depot->fbpsiz = size; return TRUE; } /* Synchronize contents of updating a database with the file and the device. */ int dpsync(DEPOT *depot){ assert(depot); if(depot->fatal){ dpecodeset(DP_EFATAL, __FILE__, __LINE__); return FALSE; } if(!depot->wmode){ dpecodeset(DP_EMODE, __FILE__, __LINE__); return FALSE; } *((int *)(depot->map + DP_FSIZOFF)) = depot->fsiz; *((int *)(depot->map + DP_RNUMOFF)) = depot->rnum; if(msync(depot->map, depot->msiz, MS_SYNC) == -1){ dpecodeset(DP_EMAP, __FILE__, __LINE__); depot->fatal = TRUE; return FALSE; } if(fsync(depot->fd) == -1){ dpecodeset(DP_ESYNC, __FILE__, __LINE__); depot->fatal = TRUE; return FALSE; } return TRUE; } /* Optimize a database. */ int dpoptimize(DEPOT *depot, int bnum){ DEPOT *tdepot; char *name; int i, err, off, head[DP_RHNUM], ee, ksizs[DP_OPTRUNIT], vsizs[DP_OPTRUNIT], unum; char ebuf[DP_ENTBUFSIZ], *kbufs[DP_OPTRUNIT], *vbufs[DP_OPTRUNIT]; assert(depot); if(depot->fatal){ dpecodeset(DP_EFATAL, __FILE__, __LINE__); return FALSE; } if(!depot->wmode){ dpecodeset(DP_EMODE, __FILE__, __LINE__); return FALSE; } if(!(name = malloc(strlen(depot->name) + strlen(DP_TMPFSUF) + 1))){ dpecodeset(DP_EALLOC, __FILE__, __LINE__); depot->fatal = FALSE; return FALSE; } sprintf(name, "%s%s", depot->name, DP_TMPFSUF); if(bnum < 0){ bnum = (int)(depot->rnum * (1.0 / DP_OPTBLOAD)) + 1; if(bnum < DP_DEFBNUM / 2) bnum = DP_DEFBNUM / 2; } if(!(tdepot = dpopen(name, DP_OWRITER | DP_OCREAT | DP_OTRUNC, bnum))){ free(name); depot->fatal = TRUE; return FALSE; } free(name); if(!dpsetflags(tdepot, dpgetflags(depot))){ dpclose(tdepot); depot->fatal = TRUE; return FALSE; } tdepot->align = depot->align; err = FALSE; off = DP_HEADSIZ + depot->bnum * sizeof(int); unum = 0; while(off < depot->fsiz){ if(!dprechead(depot, off, head, ebuf, &ee)){ err = TRUE; break; } if(!(head[DP_RHIFLAGS] & DP_RECFDEL)){ if(ee && DP_RHNUM * sizeof(int) + head[DP_RHIKSIZ] <= DP_ENTBUFSIZ){ if(!(kbufs[unum] = malloc(head[DP_RHIKSIZ] + 1))){ dpecodeset(DP_EALLOC, __FILE__, __LINE__); err = TRUE; break; } memcpy(kbufs[unum], ebuf + (DP_RHNUM * sizeof(int)), head[DP_RHIKSIZ]); if(DP_RHNUM * sizeof(int) + head[DP_RHIKSIZ] + head[DP_RHIVSIZ] <= DP_ENTBUFSIZ){ if(!(vbufs[unum] = malloc(head[DP_RHIVSIZ] + 1))){ dpecodeset(DP_EALLOC, __FILE__, __LINE__); err = TRUE; break; } memcpy(vbufs[unum], ebuf + (DP_RHNUM * sizeof(int) + head[DP_RHIKSIZ]), head[DP_RHIVSIZ]); } else { vbufs[unum] = dprecval(depot, off, head, 0, -1); } } else { kbufs[unum] = dpreckey(depot, off, head); vbufs[unum] = dprecval(depot, off, head, 0, -1); } ksizs[unum] = head[DP_RHIKSIZ]; vsizs[unum] = head[DP_RHIVSIZ]; unum++; if(unum >= DP_OPTRUNIT){ for(i = 0; i < unum; i++){ if(kbufs[i] && vbufs[i]){ if(!dpput(tdepot, kbufs[i], ksizs[i], vbufs[i], vsizs[i], DP_DKEEP)) err = TRUE; } else { err = TRUE; } free(kbufs[i]); free(vbufs[i]); if(err) break; } unum = 0; } } off += dprecsize(head); if(err) break; } for(i = 0; i < unum; i++){ if(kbufs[i] && vbufs[i]){ if(!dpput(tdepot, kbufs[i], ksizs[i], vbufs[i], vsizs[i], DP_DKEEP)) err = TRUE; } else { err = TRUE; } free(kbufs[i]); free(vbufs[i]); if(err) break; } if(!dpsync(tdepot)) err = TRUE; if(err){ unlink(tdepot->name); dpclose(tdepot); depot->fatal = TRUE; return FALSE; } if(munmap(depot->map, depot->msiz) == -1){ dpclose(tdepot); dpecodeset(DP_EMAP, __FILE__, __LINE__); depot->fatal = TRUE; return FALSE; } depot->map = MAP_FAILED; if(ftruncate(depot->fd, 0) == -1){ dpclose(tdepot); unlink(tdepot->name); dpecodeset(DP_ETRUNC, __FILE__, __LINE__); depot->fatal = TRUE; return FALSE; } if(dpfcopy(depot->fd, 0, tdepot->fd, 0) == -1){ dpclose(tdepot); unlink(tdepot->name); depot->fatal = TRUE; return FALSE; } depot->fsiz = tdepot->fsiz; depot->bnum = tdepot->bnum; depot->ioff = 0; for(i = 0; i < depot->fbpsiz; i += 2){ depot->fbpool[i] = -1; depot->fbpool[i+1] = -1; } depot->msiz = tdepot->msiz; depot->map = mmap(0, depot->msiz, PROT_READ | PROT_WRITE, MAP_SHARED, depot->fd, 0); if(depot->map == MAP_FAILED){ dpecodeset(DP_EMAP, __FILE__, __LINE__); depot->fatal = TRUE; return FALSE; } depot->buckets = (int *)(depot->map + DP_HEADSIZ); if(!(name = dpname(tdepot))){ dpclose(tdepot); unlink(tdepot->name); depot->fatal = TRUE; return FALSE; } if(!dpclose(tdepot)){ free(name); unlink(tdepot->name); depot->fatal = TRUE; return FALSE; } if(unlink(name) == -1){ free(name); dpecodeset(DP_EUNLINK, __FILE__, __LINE__); depot->fatal = TRUE; return FALSE; } free(name); return TRUE; } /* Get the name of a database. */ char *dpname(DEPOT *depot){ char *name; assert(depot); if(depot->fatal){ dpecodeset(DP_EFATAL, __FILE__, __LINE__); return NULL; } if(!(name = dpstrdup(depot->name))){ dpecodeset(DP_EALLOC, __FILE__, __LINE__); depot->fatal = TRUE; return NULL; } return name; } /* Get the size of a database file. */ int dpfsiz(DEPOT *depot){ assert(depot); if(depot->fatal){ dpecodeset(DP_EFATAL, __FILE__, __LINE__); return -1; } return depot->fsiz; } /* Get the number of the elements of the bucket array. */ int dpbnum(DEPOT *depot){ assert(depot); if(depot->fatal){ dpecodeset(DP_EFATAL, __FILE__, __LINE__); return -1; } return depot->bnum; } /* Get the number of the used elements of the bucket array. */ int dpbusenum(DEPOT *depot){ int i, hits; assert(depot); if(depot->fatal){ dpecodeset(DP_EFATAL, __FILE__, __LINE__); return -1; } hits = 0; for(i = 0; i < depot->bnum; i++){ if(depot->buckets[i]) hits++; } return hits; } /* Get the number of the records stored in a database. */ int dprnum(DEPOT *depot){ assert(depot); if(depot->fatal){ dpecodeset(DP_EFATAL, __FILE__, __LINE__); return -1; } return depot->rnum; } /* Check whether a database handle is a writer or not. */ int dpwritable(DEPOT *depot){ assert(depot); return depot->wmode; } /* Check whether a database has a fatal error or not. */ int dpfatalerror(DEPOT *depot){ assert(depot); return depot->fatal; } /* Get the inode number of a database file. */ int dpinode(DEPOT *depot){ assert(depot); return depot->inode; } /* Get the last modified time of a database. */ time_t dpmtime(DEPOT *depot){ assert(depot); return depot->mtime; } /* Get the file descriptor of a database file. */ int dpfdesc(DEPOT *depot){ assert(depot); return depot->fd; } /* Remove a database file. */ int dpremove(const char *name){ struct stat sbuf; DEPOT *depot; assert(name); if(lstat(name, &sbuf) == -1){ dpecodeset(DP_ESTAT, __FILE__, __LINE__); return FALSE; } if((depot = dpopen(name, DP_OWRITER | DP_OTRUNC, -1)) != NULL) dpclose(depot); if(unlink(name) == -1){ dpecodeset(DP_EUNLINK, __FILE__, __LINE__); return FALSE; } return TRUE; } /* Repair a broken database file. */ int dprepair(const char *name){ DEPOT *tdepot; char dbhead[DP_HEADSIZ], *tname, *kbuf, *vbuf; int fd, fsiz, flags, bnum, tbnum, err, head[DP_RHNUM], off, rsiz, ksiz, vsiz; struct stat sbuf; assert(name); if(lstat(name, &sbuf) == -1){ dpecodeset(DP_ESTAT, __FILE__, __LINE__); return FALSE; } fsiz = sbuf.st_size; if((fd = open(name, O_RDWR, DP_FILEMODE)) == -1){ dpecodeset(DP_EOPEN, __FILE__, __LINE__); return FALSE; } if(!dpseekread(fd, 0, dbhead, DP_HEADSIZ)){ close(fd); return FALSE; } flags = *(int *)(dbhead + DP_FLAGSOFF); bnum = *(int *)(dbhead + DP_BNUMOFF); tbnum = *(int *)(dbhead + DP_RNUMOFF) * 2; if(tbnum < DP_DEFBNUM) tbnum = DP_DEFBNUM; if(!(tname = malloc(strlen(name) + strlen(DP_TMPFSUF) + 1))){ dpecodeset(DP_EALLOC, __FILE__, __LINE__); return FALSE; } sprintf(tname, "%s%s", name, DP_TMPFSUF); if(!(tdepot = dpopen(tname, DP_OWRITER | DP_OCREAT | DP_OTRUNC, tbnum))){ free(tname); close(fd); return FALSE; } err = FALSE; off = DP_HEADSIZ + bnum * sizeof(int); while(off < fsiz){ if(!dpseekread(fd, off, head, DP_RHNUM * sizeof(int))) break; if(head[DP_RHIFLAGS] & DP_RECFDEL){ if((rsiz = dprecsize(head)) < 0) break; off += rsiz; continue; } ksiz = head[DP_RHIKSIZ]; vsiz = head[DP_RHIVSIZ]; if(ksiz >= 0 && vsiz >= 0){ kbuf = malloc(ksiz + 1); vbuf = malloc(vsiz + 1); if(kbuf && vbuf){ if(dpseekread(fd, off + DP_RHNUM * sizeof(int), kbuf, ksiz) && dpseekread(fd, off + DP_RHNUM * sizeof(int) + ksiz, vbuf, vsiz)){ if(!dpput(tdepot, kbuf, ksiz, vbuf, vsiz, DP_DKEEP)) err = TRUE; } else { err = TRUE; } } else { if(!err) dpecodeset(DP_EALLOC, __FILE__, __LINE__); err = TRUE; } free(vbuf); free(kbuf); } else { if(!err) dpecodeset(DP_EBROKEN, __FILE__, __LINE__); err = TRUE; } if((rsiz = dprecsize(head)) < 0) break; off += rsiz; } if(!dpsetflags(tdepot, flags)) err = TRUE; if(!dpsync(tdepot)) err = TRUE; if(ftruncate(fd, 0) == -1){ if(!err) dpecodeset(DP_ETRUNC, __FILE__, __LINE__); err = TRUE; } if(dpfcopy(fd, 0, tdepot->fd, 0) == -1) err = TRUE; if(!dpclose(tdepot)) err = TRUE; if(close(fd) == -1){ if(!err) dpecodeset(DP_ECLOSE, __FILE__, __LINE__); err = TRUE; } if(unlink(tname) == -1){ if(!err) dpecodeset(DP_EUNLINK, __FILE__, __LINE__); err = TRUE; } free(tname); return err ? FALSE : TRUE; } /* Dump all records as endian independent data. */ int dpexportdb(DEPOT *depot, const char *name){ char *kbuf, *vbuf, *pbuf; int fd, err, ksiz, vsiz, psiz; assert(depot && name); if(!(dpiterinit(depot))) return FALSE; if((fd = open(name, O_RDWR | O_CREAT | O_TRUNC, DP_FILEMODE)) == -1){ dpecodeset(DP_EOPEN, __FILE__, __LINE__); return FALSE; } err = FALSE; while(!err && (kbuf = dpiternext(depot, &ksiz)) != NULL){ if((vbuf = dpget(depot, kbuf, ksiz, 0, -1, &vsiz)) != NULL){ if((pbuf = malloc(ksiz + vsiz + DP_NUMBUFSIZ * 2)) != NULL){ psiz = 0; psiz += sprintf(pbuf + psiz, "%X\n%X\n", ksiz, vsiz); memcpy(pbuf + psiz, kbuf, ksiz); psiz += ksiz; pbuf[psiz++] = '\n'; memcpy(pbuf + psiz, vbuf, vsiz); psiz += vsiz; pbuf[psiz++] = '\n'; if(!dpwrite(fd, pbuf, psiz)){ dpecodeset(DP_EWRITE, __FILE__, __LINE__); err = TRUE; } free(pbuf); } else { dpecodeset(DP_EALLOC, __FILE__, __LINE__); err = TRUE; } free(vbuf); } else { err = TRUE; } free(kbuf); } if(close(fd) == -1){ if(!err) dpecodeset(DP_ECLOSE, __FILE__, __LINE__); return FALSE; } return !err && !dpfatalerror(depot); } /* Load all records from endian independent data. */ int dpimportdb(DEPOT *depot, const char *name){ char mbuf[DP_IOBUFSIZ], *rbuf; int i, j, fd, err, fsiz, off, msiz, ksiz, vsiz, hlen; struct stat sbuf; assert(depot && name); if(!depot->wmode){ dpecodeset(DP_EMODE, __FILE__, __LINE__); return FALSE; } if(dprnum(depot) > 0){ dpecodeset(DP_EMISC, __FILE__, __LINE__); return FALSE; } if((fd = open(name, O_RDONLY, DP_FILEMODE)) == -1){ dpecodeset(DP_EOPEN, __FILE__, __LINE__); return FALSE; } if(fstat(fd, &sbuf) == -1 || !S_ISREG(sbuf.st_mode)){ dpecodeset(DP_ESTAT, __FILE__, __LINE__); close(fd); return FALSE; } err = FALSE; fsiz = sbuf.st_size; off = 0; while(!err && off < fsiz){ msiz = fsiz - off; if(msiz > DP_IOBUFSIZ) msiz = DP_IOBUFSIZ; if(!dpseekread(fd, off, mbuf, msiz)){ err = TRUE; break; } hlen = 0; ksiz = -1; vsiz = -1; for(i = 0; i < msiz; i++){ if(mbuf[i] == '\n'){ mbuf[i] = '\0'; ksiz = strtol(mbuf, NULL, 16); for(j = i + 1; j < msiz; j++){ if(mbuf[j] == '\n'){ mbuf[j] = '\0'; vsiz = strtol(mbuf + i + 1, NULL, 16); hlen = j + 1; break; } } break; } } if(ksiz < 0 || vsiz < 0 || hlen < 4){ dpecodeset(DP_EBROKEN, __FILE__, __LINE__); err = TRUE; break; } if(hlen + ksiz + vsiz + 2 < DP_IOBUFSIZ){ if(!dpput(depot, mbuf + hlen, ksiz, mbuf + hlen + ksiz + 1, vsiz, DP_DKEEP)) err = TRUE; } else { if((rbuf = malloc(ksiz + vsiz + 2)) != NULL){ if(dpseekread(fd, off + hlen, rbuf, ksiz + vsiz + 2)){ if(!dpput(depot, rbuf, ksiz, rbuf + ksiz + 1, vsiz, DP_DKEEP)) err = TRUE; } else { err = TRUE; } free(rbuf); } else { dpecodeset(DP_EALLOC, __FILE__, __LINE__); err = TRUE; } } off += hlen + ksiz + vsiz + 2; } if(close(fd) == -1){ if(!err) dpecodeset(DP_ECLOSE, __FILE__, __LINE__); return FALSE; } return !err && !dpfatalerror(depot); } /* Retrieve a record directly from a database file. */ char *dpsnaffle(const char *name, const char* kbuf, int ksiz, int *sp){ char hbuf[DP_HEADSIZ], *map, *vbuf, *tkbuf; int fd, fsiz, bnum, msiz, *buckets, hash, thash, head[DP_RHNUM], err, off, vsiz, tksiz, kcmp; struct stat sbuf; assert(name && kbuf); if(ksiz < 0) ksiz = strlen(kbuf); if((fd = open(name, O_RDONLY, DP_FILEMODE)) == -1){ dpecodeset(DP_EOPEN, __FILE__, __LINE__); return NULL; } if(fstat(fd, &sbuf) == -1 || !S_ISREG(sbuf.st_mode)){ close(fd); dpecodeset(DP_ESTAT, __FILE__, __LINE__); return NULL; } fsiz = sbuf.st_size; if(!dpseekread(fd, 0, hbuf, DP_HEADSIZ)){ close(fd); dpecodeset(DP_EBROKEN, __FILE__, __LINE__); return NULL; } if(dpbigendian() ? memcmp(hbuf, DP_MAGICNUMB, strlen(DP_MAGICNUMB)) != 0 : memcmp(hbuf, DP_MAGICNUML, strlen(DP_MAGICNUML)) != 0){ close(fd); dpecodeset(DP_EBROKEN, __FILE__, __LINE__); return NULL; } bnum = *((int *)(hbuf + DP_BNUMOFF)); if(bnum < 1 || fsiz < DP_HEADSIZ + bnum * sizeof(int)){ close(fd); dpecodeset(DP_EBROKEN, __FILE__, __LINE__); return NULL; } msiz = DP_HEADSIZ + bnum * sizeof(int); map = mmap(0, msiz, PROT_READ, MAP_SHARED, fd, 0); if(map == MAP_FAILED){ close(fd); dpecodeset(DP_EMAP, __FILE__, __LINE__); return NULL; } buckets = (int *)(map + DP_HEADSIZ); err = FALSE; vbuf = NULL; vsiz = 0; DP_SECONDHASH(hash, kbuf, ksiz); DP_FIRSTHASH(thash, kbuf, ksiz); off = buckets[thash%bnum]; while(off != 0){ if(!dpseekread(fd, off, head, DP_RHNUM * sizeof(int))){ err = TRUE; break; } if(head[DP_RHIKSIZ] < 0 || head[DP_RHIVSIZ] < 0 || head[DP_RHIPSIZ] < 0 || head[DP_RHILEFT] < 0 || head[DP_RHIRIGHT] < 0){ dpecodeset(DP_EBROKEN, __FILE__, __LINE__); err = TRUE; break; } thash = head[DP_RHIHASH]; if(hash > thash){ off = head[DP_RHILEFT]; } else if(hash < thash){ off = head[DP_RHIRIGHT]; } else { tksiz = head[DP_RHIKSIZ]; if(!(tkbuf = malloc(tksiz + 1))){ dpecodeset(DP_EALLOC, __FILE__, __LINE__); err = TRUE; break; } if(!dpseekread(fd, off + DP_RHNUM * sizeof(int), tkbuf, tksiz)){ free(tkbuf); err = TRUE; break; } tkbuf[tksiz] = '\0'; kcmp = dpkeycmp(kbuf, ksiz, tkbuf, tksiz); free(tkbuf); if(kcmp > 0){ off = head[DP_RHILEFT]; } else if(kcmp < 0){ off = head[DP_RHIRIGHT]; } else if(head[DP_RHIFLAGS] & DP_RECFDEL){ break; } else { vsiz = head[DP_RHIVSIZ]; if(!(vbuf = malloc(vsiz + 1))){ dpecodeset(DP_EALLOC, __FILE__, __LINE__); err = TRUE; break; } if(!dpseekread(fd, off + DP_RHNUM * sizeof(int) + head[DP_RHIKSIZ], vbuf, vsiz)){ free(vbuf); vbuf = NULL; err = TRUE; break; } vbuf[vsiz] = '\0'; break; } } } if(vbuf){ if(sp) *sp = vsiz; } else if(!err){ dpecodeset(DP_ENOITEM, __FILE__, __LINE__); } munmap(map, msiz); close(fd); return vbuf; } /* Hash function used inside Depot. */ int dpinnerhash(const char *kbuf, int ksiz){ int res; assert(kbuf); if(ksiz < 0) ksiz = strlen(kbuf); DP_FIRSTHASH(res, kbuf, ksiz); return res; } /* Hash function which is independent from the hash functions used inside Depot. */ int dpouterhash(const char *kbuf, int ksiz){ int res; assert(kbuf); if(ksiz < 0) ksiz = strlen(kbuf); DP_THIRDHASH(res, kbuf, ksiz); return res; } /* Get a natural prime number not less than a number. */ int dpprimenum(int num){ assert(num > 0); return dpgetprime(num); } /************************************************************************************************* * features for experts *************************************************************************************************/ /* Name of the operating system. */ const char *dpsysname = _QDBM_SYSNAME; /* File descriptor for debugging output. */ int dpdbgfd = -1; /* Whether this build is reentrant. */ const int dpisreentrant = _qdbm_ptsafe; /* Set the last happened error code. */ void dpecodeset(int ecode, const char *file, int line){ char iobuf[DP_IOBUFSIZ]; assert(ecode >= DP_ENOERR && file && line >= 0); dpecode = ecode; if(dpdbgfd >= 0){ fflush(stdout); fflush(stderr); sprintf(iobuf, "* dpecodeset: %s:%d: [%d] %s\n", file, line, ecode, dperrmsg(ecode)); dpwrite(dpdbgfd, iobuf, strlen(iobuf)); } } /* Get the pointer of the variable of the last happened error code. */ int *dpecodeptr(void){ static int defdpecode = DP_ENOERR; void *ptr; if(_qdbm_ptsafe){ if(!(ptr = _qdbm_settsd(&defdpecode, sizeof(int), &defdpecode))){ defdpecode = DP_EMISC; return &defdpecode; } return (int *)ptr; } return &defdpecode; } /* Synchronize updating contents on memory. */ int dpmemsync(DEPOT *depot){ assert(depot); if(depot->fatal){ dpecodeset(DP_EFATAL, __FILE__, __LINE__); return FALSE; } if(!depot->wmode){ dpecodeset(DP_EMODE, __FILE__, __LINE__); return FALSE; } *((int *)(depot->map + DP_FSIZOFF)) = depot->fsiz; *((int *)(depot->map + DP_RNUMOFF)) = depot->rnum; if(msync(depot->map, depot->msiz, MS_SYNC) == -1){ dpecodeset(DP_EMAP, __FILE__, __LINE__); depot->fatal = TRUE; return FALSE; } return TRUE; } /* Synchronize updating contents on memory, not physically. */ int dpmemflush(DEPOT *depot){ assert(depot); if(depot->fatal){ dpecodeset(DP_EFATAL, __FILE__, __LINE__); return FALSE; } if(!depot->wmode){ dpecodeset(DP_EMODE, __FILE__, __LINE__); return FALSE; } *((int *)(depot->map + DP_FSIZOFF)) = depot->fsiz; *((int *)(depot->map + DP_RNUMOFF)) = depot->rnum; if(mflush(depot->map, depot->msiz, MS_SYNC) == -1){ dpecodeset(DP_EMAP, __FILE__, __LINE__); depot->fatal = TRUE; return FALSE; } return TRUE; } /* Get flags of a database. */ int dpgetflags(DEPOT *depot){ int flags; assert(depot); memcpy(&flags, depot->map + DP_FLAGSOFF, sizeof(int)); return flags; } /* Set flags of a database. */ int dpsetflags(DEPOT *depot, int flags){ assert(depot); if(!depot->wmode){ dpecodeset(DP_EMODE, __FILE__, __LINE__); return FALSE; } memcpy(depot->map + DP_FLAGSOFF, &flags, sizeof(int)); return TRUE; } /************************************************************************************************* * private objects *************************************************************************************************/ /* Check whether the byte order of the platform is big endian or not. The return value is true if bigendian, else, it is false. */ static int dpbigendian(void){ char buf[sizeof(int)]; *(int *)buf = 1; return !buf[0]; } /* Get a copied string. `str' specifies an original string. The return value is a copied string whose region is allocated by `malloc'. */ static char *dpstrdup(const char *str){ int len; char *buf; assert(str); len = strlen(str); if(!(buf = malloc(len + 1))) return NULL; memcpy(buf, str, len + 1); return buf; } /* Lock a file descriptor. `fd' specifies a file descriptor. `ex' specifies whether an exclusive lock or a shared lock is performed. `nb' specifies whether to request with non-blocking. The return value is true if successful, else, it is false. */ static int dplock(int fd, int ex, int nb){ struct flock lock; assert(fd >= 0); memset(&lock, 0, sizeof(struct flock)); lock.l_type = ex ? F_WRLCK : F_RDLCK; lock.l_whence = SEEK_SET; lock.l_start = 0; lock.l_len = 0; lock.l_pid = 0; while(fcntl(fd, nb ? F_SETLK : F_SETLKW, &lock) == -1){ if(errno != EINTR){ dpecodeset(DP_ELOCK, __FILE__, __LINE__); return FALSE; } } return TRUE; } /* Write into a file. `fd' specifies a file descriptor. `buf' specifies a buffer to write. `size' specifies the size of the buffer. The return value is the size of the written buffer, or, -1 on failure. */ static int dpwrite(int fd, const void *buf, int size){ const char *lbuf; int rv, wb; assert(fd >= 0 && buf && size >= 0); lbuf = buf; rv = 0; do { wb = write(fd, lbuf, size); switch(wb){ case -1: if(errno != EINTR) return -1; case 0: break; default: lbuf += wb; size -= wb; rv += wb; break; } } while(size > 0); return rv; } /* Write into a file at an offset. `fd' specifies a file descriptor. `off' specifies an offset of the file. `buf' specifies a buffer to write. `size' specifies the size of the buffer. The return value is true if successful, else, it is false. */ static int dpseekwrite(int fd, int off, const void *buf, int size){ assert(fd >= 0 && buf && size >= 0); if(size < 1) return TRUE; if(off < 0){ if(lseek(fd, 0, SEEK_END) == -1){ dpecodeset(DP_ESEEK, __FILE__, __LINE__); return FALSE; } } else { if(lseek(fd, off, SEEK_SET) != off){ dpecodeset(DP_ESEEK, __FILE__, __LINE__); return FALSE; } } if(dpwrite(fd, buf, size) != size){ dpecodeset(DP_EWRITE, __FILE__, __LINE__); return FALSE; } return TRUE; } /* Write an integer into a file at an offset. `fd' specifies a file descriptor. `off' specifies an offset of the file. `num' specifies an integer. The return value is true if successful, else, it is false. */ static int dpseekwritenum(int fd, int off, int num){ assert(fd >= 0); return dpseekwrite(fd, off, &num, sizeof(int)); } /* Read from a file and store the data into a buffer. `fd' specifies a file descriptor. `buffer' specifies a buffer to store into. `size' specifies the size to read with. The return value is the size read with, or, -1 on failure. */ static int dpread(int fd, void *buf, int size){ char *lbuf; int i, bs; assert(fd >= 0 && buf && size >= 0); lbuf = buf; for(i = 0; i < size && (bs = read(fd, lbuf + i, size - i)) != 0; i += bs){ if(bs == -1 && errno != EINTR) return -1; } return i; } /* Read from a file at an offset and store the data into a buffer. `fd' specifies a file descriptor. `off' specifies an offset of the file. `buffer' specifies a buffer to store into. `size' specifies the size to read with. The return value is true if successful, else, it is false. */ static int dpseekread(int fd, int off, void *buf, int size){ char *lbuf; assert(fd >= 0 && off >= 0 && buf && size >= 0); lbuf = (char *)buf; if(lseek(fd, off, SEEK_SET) != off){ dpecodeset(DP_ESEEK, __FILE__, __LINE__); return FALSE; } if(dpread(fd, lbuf, size) != size){ dpecodeset(DP_EREAD, __FILE__, __LINE__); return FALSE; } return TRUE; } /* Copy data between files. `destfd' specifies a file descriptor of a destination file. `destoff' specifies an offset of the destination file. `srcfd' specifies a file descriptor of a source file. `srcoff' specifies an offset of the source file. The return value is the size copied with, or, -1 on failure. */ static int dpfcopy(int destfd, int destoff, int srcfd, int srcoff){ char iobuf[DP_IOBUFSIZ]; int sum, iosiz; if(lseek(srcfd, srcoff, SEEK_SET) == -1 || lseek(destfd, destoff, SEEK_SET) == -1){ dpecodeset(DP_ESEEK, __FILE__, __LINE__); return -1; } sum = 0; while((iosiz = dpread(srcfd, iobuf, DP_IOBUFSIZ)) > 0){ if(dpwrite(destfd, iobuf, iosiz) == -1){ dpecodeset(DP_EWRITE, __FILE__, __LINE__); return -1; } sum += iosiz; } if(iosiz < 0){ dpecodeset(DP_EREAD, __FILE__, __LINE__); return -1; } return sum; } /* Get a natural prime number not less than a number. `num' specified a natural number. The return value is a prime number not less than the specified number. */ static int dpgetprime(int num){ int primes[] = { 1, 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 43, 47, 53, 59, 61, 71, 79, 83, 89, 103, 109, 113, 127, 139, 157, 173, 191, 199, 223, 239, 251, 283, 317, 349, 383, 409, 443, 479, 509, 571, 631, 701, 761, 829, 887, 953, 1021, 1151, 1279, 1399, 1531, 1663, 1789, 1913, 2039, 2297, 2557, 2803, 3067, 3323, 3583, 3833, 4093, 4603, 5119, 5623, 6143, 6653, 7159, 7673, 8191, 9209, 10223, 11261, 12281, 13309, 14327, 15359, 16381, 18427, 20479, 22511, 24571, 26597, 28669, 30713, 32749, 36857, 40949, 45053, 49139, 53239, 57331, 61417, 65521, 73727, 81919, 90107, 98299, 106487, 114679, 122869, 131071, 147451, 163819, 180221, 196597, 212987, 229373, 245759, 262139, 294911, 327673, 360439, 393209, 425977, 458747, 491503, 524287, 589811, 655357, 720887, 786431, 851957, 917503, 982981, 1048573, 1179641, 1310719, 1441771, 1572853, 1703903, 1835003, 1966079, 2097143, 2359267, 2621431, 2883577, 3145721, 3407857, 3670013, 3932153, 4194301, 4718579, 5242877, 5767129, 6291449, 6815741, 7340009, 7864301, 8388593, 9437179, 10485751, 11534329, 12582893, 13631477, 14680063, 15728611, 16777213, 18874367, 20971507, 23068667, 25165813, 27262931, 29360087, 31457269, 33554393, 37748717, 41943023, 46137319, 50331599, 54525917, 58720253, 62914549, 67108859, 75497467, 83886053, 92274671, 100663291, 109051903, 117440509, 125829103, 134217689, 150994939, 167772107, 184549373, 201326557, 218103799, 234881011, 251658227, 268435399, 301989881, 335544301, 369098707, 402653171, 436207613, 469762043, 503316469, 536870909, 603979769, 671088637, 738197503, 805306357, 872415211, 939524087, 1006632947, 1073741789, 1207959503, 1342177237, 1476394991, 1610612711, 1744830457, 1879048183, 2013265907, -1 }; int i; assert(num > 0); for(i = 0; primes[i] > 0; i++){ if(num <= primes[i]) return primes[i]; } return primes[i-1]; } /* Get the padding size of a record. `vsiz' specifies the size of the value of a record. The return value is the padding size of a record. */ static int dppadsize(DEPOT *depot, int ksiz, int vsiz){ int pad; assert(depot && vsiz >= 0); if(depot->align > 0){ return depot->align - (depot->fsiz + DP_RHNUM * sizeof(int) + ksiz + vsiz) % depot->align; } else if(depot->align < 0){ pad = (int)(vsiz * (2.0 / (1 << -(depot->align)))); if(vsiz + pad >= DP_FSBLKSIZ){ if(vsiz <= DP_FSBLKSIZ) pad = 0; if(depot->fsiz % DP_FSBLKSIZ == 0){ return (pad / DP_FSBLKSIZ) * DP_FSBLKSIZ + DP_FSBLKSIZ - (depot->fsiz + DP_RHNUM * sizeof(int) + ksiz + vsiz) % DP_FSBLKSIZ; } else { return (pad / (DP_FSBLKSIZ / 2)) * (DP_FSBLKSIZ / 2) + (DP_FSBLKSIZ / 2) - (depot->fsiz + DP_RHNUM * sizeof(int) + ksiz + vsiz) % (DP_FSBLKSIZ / 2); } } else { return pad >= DP_RHNUM * sizeof(int) ? pad : DP_RHNUM * sizeof(int); } } return 0; } /* Get the size of a record in a database file. `head' specifies the header of a record. The return value is the size of a record in a database file. */ static int dprecsize(int *head){ assert(head); return DP_RHNUM * sizeof(int) + head[DP_RHIKSIZ] + head[DP_RHIVSIZ] + head[DP_RHIPSIZ]; } /* Read the header of a record. `depot' specifies a database handle. `off' specifies an offset of the database file. `head' specifies a buffer for the header. `ebuf' specifies the pointer to the entity buffer. `eep' specifies the pointer to a variable to which whether ebuf was used is assigned. The return value is true if successful, else, it is false. */ static int dprechead(DEPOT *depot, int off, int *head, char *ebuf, int *eep){ assert(depot && off >= 0 && head); if(off > depot->fsiz){ dpecodeset(DP_EBROKEN, __FILE__, __LINE__); return FALSE; } if(ebuf){ *eep = FALSE; if(off < depot->fsiz - DP_ENTBUFSIZ){ *eep = TRUE; if(!dpseekread(depot->fd, off, ebuf, DP_ENTBUFSIZ)) return FALSE; memcpy(head, ebuf, DP_RHNUM * sizeof(int)); if(head[DP_RHIKSIZ] < 0 || head[DP_RHIVSIZ] < 0 || head[DP_RHIPSIZ] < 0 || head[DP_RHILEFT] < 0 || head[DP_RHIRIGHT] < 0){ dpecodeset(DP_EBROKEN, __FILE__, __LINE__); return FALSE; } return TRUE; } } if(!dpseekread(depot->fd, off, head, DP_RHNUM * sizeof(int))) return FALSE; if(head[DP_RHIKSIZ] < 0 || head[DP_RHIVSIZ] < 0 || head[DP_RHIPSIZ] < 0 || head[DP_RHILEFT] < 0 || head[DP_RHIRIGHT] < 0){ dpecodeset(DP_EBROKEN, __FILE__, __LINE__); return FALSE; } return TRUE; } /* Read the entitiy of the key of a record. `depot' specifies a database handle. `off' specifies an offset of the database file. `head' specifies the header of a record. The return value is a key data whose region is allocated by `malloc', or NULL on failure. */ static char *dpreckey(DEPOT *depot, int off, int *head){ char *kbuf; int ksiz; assert(depot && off >= 0); ksiz = head[DP_RHIKSIZ]; if(!(kbuf = malloc(ksiz + 1))){ dpecodeset(DP_EALLOC, __FILE__, __LINE__); return NULL; } if(!dpseekread(depot->fd, off + DP_RHNUM * sizeof(int), kbuf, ksiz)){ free(kbuf); return NULL; } kbuf[ksiz] = '\0'; return kbuf; } /* Read the entitiy of the value of a record. `depot' specifies a database handle. `off' specifies an offset of the database file. `head' specifies the header of a record. `start' specifies the offset address of the beginning of the region of the value to be read. `max' specifies the max size to be read. If it is negative, the size to read is unlimited. The return value is a value data whose region is allocated by `malloc', or NULL on failure. */ static char *dprecval(DEPOT *depot, int off, int *head, int start, int max){ char *vbuf; int vsiz; assert(depot && off >= 0 && start >= 0); head[DP_RHIVSIZ] -= start; if(max < 0){ vsiz = head[DP_RHIVSIZ]; } else { vsiz = max < head[DP_RHIVSIZ] ? max : head[DP_RHIVSIZ]; } if(!(vbuf = malloc(vsiz + 1))){ dpecodeset(DP_EALLOC, __FILE__, __LINE__); return NULL; } if(!dpseekread(depot->fd, off + DP_RHNUM * sizeof(int) + head[DP_RHIKSIZ] + start, vbuf, vsiz)){ free(vbuf); return NULL; } vbuf[vsiz] = '\0'; return vbuf; } /* Read the entitiy of the value of a record and write it into a given buffer. `depot' specifies a database handle. `off' specifies an offset of the database file. `head' specifies the header of a record. `start' specifies the offset address of the beginning of the region of the value to be read. `max' specifies the max size to be read. It shuld be less than the size of the writing buffer. If successful, the return value is the size of the written data, else, it is -1. */ static int dprecvalwb(DEPOT *depot, int off, int *head, int start, int max, char *vbuf){ int vsiz; assert(depot && off >= 0 && start >= 0 && max >= 0 && vbuf); head[DP_RHIVSIZ] -= start; vsiz = max < head[DP_RHIVSIZ] ? max : head[DP_RHIVSIZ]; if(!dpseekread(depot->fd, off + DP_RHNUM * sizeof(int) + head[DP_RHIKSIZ] + start, vbuf, vsiz)) return -1; return vsiz; } /* Compare two keys. `abuf' specifies the pointer to the region of the former. `asiz' specifies the size of the region. `bbuf' specifies the pointer to the region of the latter. `bsiz' specifies the size of the region. The return value is 0 if two equals, positive if the formar is big, else, negative. */ static int dpkeycmp(const char *abuf, int asiz, const char *bbuf, int bsiz){ assert(abuf && asiz >= 0 && bbuf && bsiz >= 0); if(asiz > bsiz) return 1; if(asiz < bsiz) return -1; return memcmp(abuf, bbuf, asiz); } /* Search for a record. `depot' specifies a database handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region. `hash' specifies the second hash value of the key. `bip' specifies the pointer to the region to assign the index of the corresponding record. `offp' specifies the pointer to the region to assign the last visited node in the hash chain, or, -1 if the hash chain is empty. `entp' specifies the offset of the last used joint, or, -1 if the hash chain is empty. `head' specifies the pointer to the region to store the header of the last visited record in. `ebuf' specifies the pointer to the entity buffer. `eep' specifies the pointer to a variable to which whether ebuf was used is assigned. `delhit' specifies whether a deleted record corresponds or not. The return value is 0 if successful, 1 if there is no corresponding record, -1 on error. */ static int dprecsearch(DEPOT *depot, const char *kbuf, int ksiz, int hash, int *bip, int *offp, int *entp, int *head, char *ebuf, int *eep, int delhit){ int off, entoff, thash, kcmp; char stkey[DP_STKBUFSIZ], *tkey; assert(depot && kbuf && ksiz >= 0 && hash >= 0 && bip && offp && entp && head && ebuf && eep); DP_FIRSTHASH(thash, kbuf, ksiz); *bip = thash % depot->bnum; off = depot->buckets[*bip]; *offp = -1; *entp = -1; entoff = -1; *eep = FALSE; while(off != 0){ if(!dprechead(depot, off, head, ebuf, eep)) return -1; thash = head[DP_RHIHASH]; if(hash > thash){ entoff = off + DP_RHILEFT * sizeof(int); off = head[DP_RHILEFT]; } else if(hash < thash){ entoff = off + DP_RHIRIGHT * sizeof(int); off = head[DP_RHIRIGHT]; } else { if(*eep && DP_RHNUM * sizeof(int) + head[DP_RHIKSIZ] <= DP_ENTBUFSIZ){ kcmp = dpkeycmp(kbuf, ksiz, ebuf + (DP_RHNUM * sizeof(int)), head[DP_RHIKSIZ]); } else if(head[DP_RHIKSIZ] > DP_STKBUFSIZ){ if(!(tkey = dpreckey(depot, off, head))) return -1; kcmp = dpkeycmp(kbuf, ksiz, tkey, head[DP_RHIKSIZ]); free(tkey); } else { if(!dpseekread(depot->fd, off + DP_RHNUM * sizeof(int), stkey, head[DP_RHIKSIZ])) return -1; kcmp = dpkeycmp(kbuf, ksiz, stkey, head[DP_RHIKSIZ]); } if(kcmp > 0){ entoff = off + DP_RHILEFT * sizeof(int); off = head[DP_RHILEFT]; } else if(kcmp < 0){ entoff = off + DP_RHIRIGHT * sizeof(int); off = head[DP_RHIRIGHT]; } else { if(!delhit && (head[DP_RHIFLAGS] & DP_RECFDEL)){ entoff = off + DP_RHILEFT * sizeof(int); off = head[DP_RHILEFT]; } else { *offp = off; *entp = entoff; return 0; } } } } *offp = off; *entp = entoff; return 1; } /* Overwrite a record. `depot' specifies a database handle. `off' specifies the offset of the database file. `rsiz' specifies the size of the existing record. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region. `vbuf' specifies the pointer to the region of a value. `vsiz' specifies the size of the region. `hash' specifies the second hash value of the key. `left' specifies the offset of the left child. `right' specifies the offset of the right child. The return value is true if successful, or, false on failure. */ static int dprecrewrite(DEPOT *depot, int off, int rsiz, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int hash, int left, int right){ char ebuf[DP_WRTBUFSIZ]; int i, head[DP_RHNUM], asiz, hoff, koff, voff, mi, min, size; assert(depot && off >= 1 && rsiz > 0 && kbuf && ksiz >= 0 && vbuf && vsiz >= 0); head[DP_RHIFLAGS] = 0; head[DP_RHIHASH] = hash; head[DP_RHIKSIZ] = ksiz; head[DP_RHIVSIZ] = vsiz; head[DP_RHIPSIZ] = rsiz - sizeof(head) - ksiz - vsiz; head[DP_RHILEFT] = left; head[DP_RHIRIGHT] = right; asiz = sizeof(head) + ksiz + vsiz; if(depot->fbpsiz > DP_FBPOOLSIZ * 4 && head[DP_RHIPSIZ] > asiz){ rsiz = (head[DP_RHIPSIZ] - asiz) / 2 + asiz; head[DP_RHIPSIZ] -= rsiz; } else { rsiz = 0; } if(asiz <= DP_WRTBUFSIZ){ memcpy(ebuf, head, sizeof(head)); memcpy(ebuf + sizeof(head), kbuf, ksiz); memcpy(ebuf + sizeof(head) + ksiz, vbuf, vsiz); if(!dpseekwrite(depot->fd, off, ebuf, asiz)) return FALSE; } else { hoff = off; koff = hoff + sizeof(head); voff = koff + ksiz; if(!dpseekwrite(depot->fd, hoff, head, sizeof(head)) || !dpseekwrite(depot->fd, koff, kbuf, ksiz) || !dpseekwrite(depot->fd, voff, vbuf, vsiz)) return FALSE; } if(rsiz > 0){ off += sizeof(head) + ksiz + vsiz + head[DP_RHIPSIZ]; head[DP_RHIFLAGS] = DP_RECFDEL | DP_RECFREUSE; head[DP_RHIHASH] = hash; head[DP_RHIKSIZ] = ksiz; head[DP_RHIVSIZ] = vsiz; head[DP_RHIPSIZ] = rsiz - sizeof(head) - ksiz - vsiz; head[DP_RHILEFT] = 0; head[DP_RHIRIGHT] = 0; if(!dpseekwrite(depot->fd, off, head, sizeof(head))) return FALSE; size = dprecsize(head); mi = -1; min = -1; for(i = 0; i < depot->fbpsiz; i += 2){ if(depot->fbpool[i] == -1){ depot->fbpool[i] = off; depot->fbpool[i+1] = size; dpfbpoolcoal(depot); mi = -1; break; } if(mi == -1 || depot->fbpool[i+1] < min){ mi = i; min = depot->fbpool[i+1]; } } if(mi >= 0 && size > min){ depot->fbpool[mi] = off; depot->fbpool[mi+1] = size; dpfbpoolcoal(depot); } } return TRUE; } /* Write a record at the end of a database file. `depot' specifies a database handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region. `vbuf' specifies the pointer to the region of a value. `vsiz' specifies the size of the region. `hash' specifies the second hash value of the key. `left' specifies the offset of the left child. `right' specifies the offset of the right child. The return value is the offset of the record, or, -1 on failure. */ static int dprecappend(DEPOT *depot, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int hash, int left, int right){ char ebuf[DP_WRTBUFSIZ], *hbuf; int head[DP_RHNUM], asiz, psiz, off; assert(depot && kbuf && ksiz >= 0 && vbuf && vsiz >= 0); psiz = dppadsize(depot, ksiz, vsiz); head[DP_RHIFLAGS] = 0; head[DP_RHIHASH] = hash; head[DP_RHIKSIZ] = ksiz; head[DP_RHIVSIZ] = vsiz; head[DP_RHIPSIZ] = psiz; head[DP_RHILEFT] = left; head[DP_RHIRIGHT] = right; asiz = sizeof(head) + ksiz + vsiz + psiz; off = depot->fsiz; if(asiz <= DP_WRTBUFSIZ){ memcpy(ebuf, head, sizeof(head)); memcpy(ebuf + sizeof(head), kbuf, ksiz); memcpy(ebuf + sizeof(head) + ksiz, vbuf, vsiz); memset(ebuf + sizeof(head) + ksiz + vsiz, 0, psiz); if(!dpseekwrite(depot->fd, off, ebuf, asiz)) return -1; } else { if(!(hbuf = malloc(asiz))){ dpecodeset(DP_EALLOC, __FILE__, __LINE__); return -1; } memcpy(hbuf, head, sizeof(head)); memcpy(hbuf + sizeof(head), kbuf, ksiz); memcpy(hbuf + sizeof(head) + ksiz, vbuf, vsiz); memset(hbuf + sizeof(head) + ksiz + vsiz, 0, psiz); if(!dpseekwrite(depot->fd, off, hbuf, asiz)){ free(hbuf); return -1; } free(hbuf); } depot->fsiz += asiz; return off; } /* Overwrite the value of a record. `depot' specifies a database handle. `off' specifies the offset of the database file. `head' specifies the header of the record. `vbuf' specifies the pointer to the region of a value. `vsiz' specifies the size of the region. `cat' specifies whether it is concatenate mode or not. The return value is true if successful, or, false on failure. */ static int dprecover(DEPOT *depot, int off, int *head, const char *vbuf, int vsiz, int cat){ int i, hsiz, hoff, voff; assert(depot && off >= 0 && head && vbuf && vsiz >= 0); for(i = 0; i < depot->fbpsiz; i += 2){ if(depot->fbpool[i] == off){ depot->fbpool[i] = -1; depot->fbpool[i+1] = -1; break; } } if(cat){ head[DP_RHIFLAGS] = 0; head[DP_RHIPSIZ] -= vsiz; head[DP_RHIVSIZ] += vsiz; hsiz = DP_RHNUM * sizeof(int); hoff = off; voff = hoff + DP_RHNUM * sizeof(int) + head[DP_RHIKSIZ] + head[DP_RHIVSIZ] - vsiz; } else { head[DP_RHIFLAGS] = 0; head[DP_RHIPSIZ] += head[DP_RHIVSIZ] - vsiz; head[DP_RHIVSIZ] = vsiz; hsiz = DP_RHNUM * sizeof(int); hoff = off; voff = hoff + DP_RHNUM * sizeof(int) + head[DP_RHIKSIZ]; } if(!dpseekwrite(depot->fd, hoff, head, hsiz) || !dpseekwrite(depot->fd, voff, vbuf, vsiz)) return FALSE; return TRUE; } /* Delete a record. `depot' specifies a database handle. `off' specifies the offset of the database file. `head' specifies the header of the record. `reusable' specifies whether the region is reusable or not. The return value is true if successful, or, false on failure. */ static int dprecdelete(DEPOT *depot, int off, int *head, int reusable){ int i, mi, min, size; assert(depot && off >= 0 && head); if(reusable){ size = dprecsize(head); mi = -1; min = -1; for(i = 0; i < depot->fbpsiz; i += 2){ if(depot->fbpool[i] == -1){ depot->fbpool[i] = off; depot->fbpool[i+1] = size; dpfbpoolcoal(depot); mi = -1; break; } if(mi == -1 || depot->fbpool[i+1] < min){ mi = i; min = depot->fbpool[i+1]; } } if(mi >= 0 && size > min){ depot->fbpool[mi] = off; depot->fbpool[mi+1] = size; dpfbpoolcoal(depot); } } return dpseekwritenum(depot->fd, off + DP_RHIFLAGS * sizeof(int), DP_RECFDEL | (reusable ? DP_RECFREUSE : 0)); } /* Make contiguous records of the free block pool coalesce. `depot' specifies a database handle. */ static void dpfbpoolcoal(DEPOT *depot){ int i; assert(depot); if(depot->fbpinc++ <= depot->fbpsiz / 4) return; depot->fbpinc = 0; qsort(depot->fbpool, depot->fbpsiz / 2, sizeof(int) * 2, dpfbpoolcmp); for(i = 2; i < depot->fbpsiz; i += 2){ if(depot->fbpool[i-2] > 0 && depot->fbpool[i-2] + depot->fbpool[i-1] - depot->fbpool[i] == 0){ depot->fbpool[i] = depot->fbpool[i-2]; depot->fbpool[i+1] += depot->fbpool[i-1]; depot->fbpool[i-2] = -1; depot->fbpool[i-1] = -1; } } } /* Compare two records of the free block pool. `a' specifies the pointer to one record. `b' specifies the pointer to the other record. The return value is 0 if two equals, positive if the formar is big, else, negative. */ static int dpfbpoolcmp(const void *a, const void *b){ assert(a && b); return *(int *)a - *(int *)b; } /* END OF FILE */ qdbm-1.8.78/crtest.c0000644000175000017500000005351510610630067013224 0ustar mikiomikio/************************************************************************************************* * Test cases of Curia * Copyright (C) 2000-2007 Mikio Hirabayashi * This file is part of QDBM, Quick Database Manager. * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU * Lesser General Public License as published by the Free Software Foundation; either version * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * You should have received a copy of the GNU Lesser General Public License along with QDBM; if * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. *************************************************************************************************/ #include #include #include #include #include #include #include #include #include #undef TRUE #define TRUE 1 /* boolean true */ #undef FALSE #define FALSE 0 /* boolean false */ #define RECBUFSIZ 32 /* buffer for records */ /* for RISC OS */ #if defined(__riscos__) || defined(__riscos) #include int __riscosify_control = __RISCOSIFY_NO_PROCESS; #endif /* global variables */ const char *progname; /* program name */ /* function prototypes */ int main(int argc, char **argv); void usage(void); int runwrite(int argc, char **argv); int runread(int argc, char **argv); int runrcat(int argc, char **argv); int runcombo(int argc, char **argv); int runwicked(int argc, char **argv); int printfflush(const char *format, ...); void pdperror(const char *name); int myrand(void); int dowrite(const char *name, int rnum, int bnum, int dnum, int sparse, int lob); int doread(const char *name, int wb, int lob); int dorcat(const char *name, int rnum, int bnum, int dnum, int pnum, int align, int fbpsiz, int cb); int docombo(const char *name); int dowicked(const char *name, int rnum, int cb); /* main routine */ int main(int argc, char **argv){ char *env; int rv; cbstdiobin(); if((env = getenv("QDBMDBGFD")) != NULL) dpdbgfd = atoi(env); progname = argv[0]; if(argc < 2) usage(); rv = 0; if(!strcmp(argv[1], "write")){ rv = runwrite(argc, argv); } else if(!strcmp(argv[1], "read")){ rv = runread(argc, argv); } else if(!strcmp(argv[1], "rcat")){ rv = runrcat(argc, argv); } else if(!strcmp(argv[1], "combo")){ rv = runcombo(argc, argv); } else if(!strcmp(argv[1], "wicked")){ rv = runwicked(argc, argv); } else { usage(); } return rv; } /* print the usage and exit */ void usage(void){ fprintf(stderr, "%s: test cases for Curia\n", progname); fprintf(stderr, "\n"); fprintf(stderr, "usage:\n"); fprintf(stderr, " %s write [-s] [-lob] name rnum bnum dnum\n", progname); fprintf(stderr, " %s read [-wb] [-lob] name\n", progname); fprintf(stderr, " %s rcat [-c] name rnum bnum dnum pnum align fbpsiz\n", progname); fprintf(stderr, " %s combo name\n", progname); fprintf(stderr, " %s wicked [-c] name rnum\n", progname); fprintf(stderr, "\n"); exit(1); } /* parse arguments of write command */ int runwrite(int argc, char **argv){ char *name, *rstr, *bstr, *dstr; int i, rnum, bnum, dnum, sb, lob, rv; name = NULL; rstr = NULL; bstr = NULL; dstr = NULL; rnum = 0; bnum = 0; dnum = 0; sb = FALSE; lob = FALSE; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ if(!strcmp(argv[i], "-s")){ sb = TRUE; } else if(!strcmp(argv[i], "-lob")){ lob = TRUE; } else { usage(); } } else if(!name){ name = argv[i]; } else if(!rstr){ rstr = argv[i]; } else if(!bstr){ bstr = argv[i]; } else if(!dstr){ dstr = argv[i]; } else { usage(); } } if(!name || !rstr || !bstr || !dstr) usage(); rnum = atoi(rstr); bnum = atoi(bstr); dnum = atoi(dstr); if(rnum < 1 || bnum < 1 || dnum < 1) usage(); rv = dowrite(name, rnum, bnum, dnum, sb, lob); return rv; } /* parse arguments of read command */ int runread(int argc, char **argv){ char *name; int i, wb, lob, rv; name = NULL; wb = FALSE; lob = FALSE; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ if(!strcmp(argv[i], "-wb")){ wb = TRUE; } else if(!strcmp(argv[i], "-lob")){ lob = TRUE; } else { usage(); } } else if(!name){ name = argv[i]; } else { usage(); } } if(!name) usage(); rv = doread(name, wb, lob); return rv; } /* parse arguments of rcat command */ int runrcat(int argc, char **argv){ char *name, *rstr, *bstr, *dstr, *pstr, *astr, *fstr; int i, rnum, bnum, dnum, pnum, align, fbpsiz, cb, rv; name = NULL; rstr = NULL; bstr = NULL; dstr = NULL; pstr = NULL; astr = NULL; fstr = NULL; rnum = 0; bnum = 0; pnum = 0; align = 0; fbpsiz = 0; cb = FALSE; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ if(!strcmp(argv[i], "-c")){ cb = TRUE; } else { usage(); } } else if(!name){ name = argv[i]; } else if(!rstr){ rstr = argv[i]; } else if(!bstr){ bstr = argv[i]; } else if(!dstr){ dstr = argv[i]; } else if(!pstr){ pstr = argv[i]; } else if(!astr){ astr = argv[i]; } else if(!fstr){ fstr = argv[i]; } else { usage(); } } if(!name || !rstr || !bstr || !dstr || !pstr || !astr || !fstr) usage(); rnum = atoi(rstr); bnum = atoi(bstr); dnum = atoi(dstr); pnum = atoi(pstr); align = atoi(astr); fbpsiz = atoi(fstr); if(rnum < 1 || bnum < 1 || dnum < 1 || pnum < 1 || fbpsiz < 0) usage(); rv = dorcat(name, rnum, bnum, dnum, pnum, align, fbpsiz, cb); return rv; } /* parse arguments of combo command */ int runcombo(int argc, char **argv){ char *name; int i, rv; name = NULL; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ usage(); } else if(!name){ name = argv[i]; } else { usage(); } } if(!name) usage(); rv = docombo(name); return rv; } /* parse arguments of wicked command */ int runwicked(int argc, char **argv){ char *name, *rstr; int i, rnum, cb, rv; name = NULL; rstr = NULL; rnum = 0; cb = FALSE; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ if(!strcmp(argv[i], "-c")){ cb = TRUE; } else { usage(); } } else if(!name){ name = argv[i]; } else if(!rstr){ rstr = argv[i]; } else { usage(); } } if(!name || !rstr) usage(); rnum = atoi(rstr); if(rnum < 1) usage(); rv = dowicked(name, rnum, cb); return rv; } /* print formatted string and flush the buffer */ int printfflush(const char *format, ...){ va_list ap; int rv; va_start(ap, format); rv = vprintf(format, ap); if(fflush(stdout) == EOF) rv = -1; va_end(ap); return rv; } /* print an error message */ void pdperror(const char *name){ fprintf(stderr, "%s: %s: %s\n", progname, name, dperrmsg(dpecode)); } /* pseudo random number generator */ int myrand(void){ static int cnt = 0; if(cnt == 0) srand(time(NULL)); return (rand() * rand() + (rand() >> (sizeof(int) * 4)) + (cnt++)) & INT_MAX; } /* perform write command */ int dowrite(const char *name, int rnum, int bnum, int dnum, int sparse, int lob){ CURIA *curia; int i, omode, err, len; char buf[RECBUFSIZ]; printfflush("\n name=%s rnum=%d bnum=%d dnum=%d s=%d lob=%d\n\n", name, rnum, bnum, dnum, sparse, lob); /* open a database */ omode = CR_OWRITER | CR_OCREAT | CR_OTRUNC | (sparse ? CR_OSPARSE : 0); if(!(curia = cropen(name, omode, bnum, dnum))){ pdperror(name); return 1; } err = FALSE; /* loop for each record */ for(i = 1; i <= rnum; i++){ /* store a record */ len = sprintf(buf, "%08d", i); if(lob){ if(!crputlob(curia, buf, len, buf, len, CR_DOVER)){ pdperror(name); err = TRUE; break; } } else { if(!crput(curia, buf, len, buf, len, CR_DOVER)){ pdperror(name); err = TRUE; break; } } /* print progression */ if(rnum > 250 && i % (rnum / 250) == 0){ putchar('.'); fflush(stdout); if(i == rnum || i % (rnum / 10) == 0){ printfflush(" (%08d)\n", i); } } } /* close the database */ if(!crclose(curia)){ pdperror(name); return 1; } if(!err) printfflush("ok\n\n"); return err ? 1 : 0; } /* perform read command */ int doread(const char *name, int wb, int lob){ CURIA *curia; int i, rnum, err, len; char buf[RECBUFSIZ], vbuf[RECBUFSIZ], *val; printfflush("\n name=%s wb=%d lob=%d\n\n", name, wb, lob); /* open a database */ if(!(curia = cropen(name, CR_OREADER, -1, -1))){ pdperror(name); return 1; } /* get the number of records */ if(lob){ rnum = crrnumlob(curia); } else { rnum = crrnum(curia); } err = FALSE; /* loop for each record */ for(i = 1; i <= rnum; i++){ /* retrieve a record */ len = sprintf(buf, "%08d", i); if(lob){ if(!(val = crgetlob(curia, buf, len, 0, -1, NULL))){ pdperror(name); err = TRUE; break; } free(val); } else if(wb){ if(crgetwb(curia, buf, len, 0, RECBUFSIZ, vbuf) == -1){ pdperror(name); err = TRUE; break; } } else { if(!(val = crget(curia, buf, len, 0, -1, NULL))){ pdperror(name); err = TRUE; break; } free(val); } /* print progression */ if(rnum > 250 && i % (rnum / 250) == 0){ putchar('.'); fflush(stdout); if(i == rnum || i % (rnum / 10) == 0){ printfflush(" (%08d)\n", i); } } } /* close the database */ if(!crclose(curia)){ pdperror(name); return 1; } if(!err) printfflush("ok\n\n"); return err ? 1 : 0; } /* perform rcat command */ int dorcat(const char *name, int rnum, int bnum, int dnum, int pnum, int align, int fbpsiz, int cb){ CURIA *curia; CBMAP *map; int i, err, len, ksiz, vsiz, rsiz; const char *kbuf, *vbuf; char buf[RECBUFSIZ], *rbuf; printfflush("\n name=%s rnum=%d bnum=%d dnum=%d pnum=%d" " align=%d fbpsiz=%d c=%d\n\n", name, rnum, bnum, dnum, pnum, align, fbpsiz, cb); if(!(curia = cropen(name, CR_OWRITER | CR_OCREAT | CR_OTRUNC, bnum, dnum))){ pdperror(name); return 1; } if(!crsetalign(curia, align) || !crsetfbpsiz(curia, fbpsiz)){ pdperror(name); crclose(curia); return 1; } map = NULL; if(cb) map = cbmapopen(); err = FALSE; for(i = 1; i <= rnum; i++){ len = sprintf(buf, "%08d", myrand() % pnum + 1); if(!crput(curia, buf, len, buf, len, CR_DCAT)){ pdperror(name); err = TRUE; break; } if(rnum > 250 && i % (rnum / 250) == 0){ putchar('.'); fflush(stdout); if(i == rnum || i % (rnum / 10) == 0){ printfflush(" (%08d: fsiz=%d rnum=%d)\n", i, crfsiz(curia), crrnum(curia)); } } } if(map){ printfflush("Matching records ... "); cbmapiterinit(map); while((kbuf = cbmapiternext(map, &ksiz)) != NULL){ vbuf = cbmapget(map, kbuf, ksiz, &vsiz); if(!(rbuf = crget(curia, kbuf, ksiz, 0, -1, &rsiz))){ pdperror(name); err = TRUE; break; } if(rsiz != vsiz || memcmp(rbuf, vbuf, rsiz)){ fprintf(stderr, "%s: %s: unmatched record\n", progname, name); free(rbuf); err = TRUE; break; } free(rbuf); } cbmapclose(map); if(!err) printfflush("ok\n"); } if(!crclose(curia)){ pdperror(name); return 1; } if(!err) printfflush("ok\n\n"); return err ? 1 : 0; } /* perform combo command */ int docombo(const char *name){ CURIA *curia; char buf[RECBUFSIZ], wbuf[RECBUFSIZ], *vbuf; int i, len, wlen, vsiz; printfflush("\n name=%s\n\n", name); printfflush("Creating a database with bnum 3 ... "); if(!(curia = cropen(name, CR_OWRITER | CR_OCREAT | CR_OTRUNC, 3, 3))){ pdperror(name); return 1; } printfflush("ok\n"); printfflush("Setting alignment as 16 ... "); if(!crsetalign(curia, 16)){ pdperror(name); crclose(curia); return 1; } printfflush("ok\n"); printfflush("Adding 20 records ... "); for(i = 1; i <= 20; i++){ len = sprintf(buf, "%08d", i); if(!crput(curia, buf, len, buf, len, CR_DOVER)){ pdperror(name); crclose(curia); return 1; } } printfflush("ok\n"); printfflush("Checking records ... "); for(i = 1; i <= 20; i++){ len = sprintf(buf, "%08d", i); if(!(vbuf = crget(curia, buf, len, 0, -1, &vsiz))){ pdperror(name); crclose(curia); return 1; } free(vbuf); if(vsiz != crvsiz(curia, buf, len)){ fprintf(stderr, "%s: %s: invalid vsiz\n", progname, name); crclose(curia); return 1; } } printfflush("ok\n"); printfflush("Overwriting top 10 records without moving rooms ... "); for(i = 1; i <= 10; i++){ len = sprintf(buf, "%08d", i); if(!crput(curia, buf, len, buf, len, CR_DOVER)){ pdperror(name); crclose(curia); return 1; } } printfflush("ok\n"); printfflush("Overwriting top 5 records with moving rooms ... "); for(i = 1; i <= 5; i++){ len = sprintf(buf, "%08d", i); wlen = sprintf(wbuf, "%024d", i); if(!crput(curia, buf, len, wbuf, wlen, CR_DOVER)){ pdperror(name); crclose(curia); return 1; } } printfflush("ok\n"); printfflush("Overwriting top 15 records in concatenation with moving rooms ... "); for(i = 1; i <= 15; i++){ len = sprintf(buf, "%08d", i); wlen = sprintf(wbuf, "========================"); if(!crput(curia, buf, len, wbuf, wlen, CR_DCAT)){ pdperror(name); crclose(curia); return 1; } } printfflush("ok\n"); printfflush("Checking records ... "); for(i = 1; i <= 20; i++){ len = sprintf(buf, "%08d", i); if(!(vbuf = crget(curia, buf, len, 0, -1, &vsiz))){ pdperror(name); crclose(curia); return 1; } free(vbuf); if(vsiz != crvsiz(curia, buf, len)){ fprintf(stderr, "%s: %s: invalid vsiz\n", progname, name); crclose(curia); return 1; } } printfflush("ok\n"); printfflush("Deleting top 10 records ... "); for(i = 1; i <= 10; i++){ len = sprintf(buf, "%08d", i); if(!crout(curia, buf, len)){ pdperror(name); crclose(curia); return 1; } } printfflush("ok\n"); printfflush("Checking deleted records ... "); for(i = 1; i <= 10; i++){ len = sprintf(buf, "%08d", i); vbuf = crget(curia, buf, len, 0, -1, &vsiz); free(vbuf); if(vbuf || dpecode != DP_ENOITEM){ fprintf(stderr, "%s: %s: deleting failed\n", progname, name); crclose(curia); return 1; } } printfflush("ok\n"); printfflush("Overwriting top 15 records in concatenation with moving rooms ... "); for(i = 1; i <= 15; i++){ len = sprintf(buf, "%08d", i); wlen = sprintf(wbuf, "========================"); if(!crput(curia, buf, len, wbuf, wlen, CR_DCAT)){ pdperror(name); crclose(curia); return 1; } } printfflush("ok\n"); printfflush("Checking records ... "); for(i = 1; i <= 20; i++){ len = sprintf(buf, "%08d", i); if(!(vbuf = crget(curia, buf, len, 0, -1, &vsiz))){ pdperror(name); crclose(curia); return 1; } free(vbuf); if(vsiz != crvsiz(curia, buf, len)){ fprintf(stderr, "%s: %s: invalid vsiz\n", progname, name); crclose(curia); return 1; } } printfflush("ok\n"); printfflush("Optimizing the database ... "); if(!croptimize(curia, -1)){ pdperror(name); crclose(curia); return 1; } printfflush("ok\n"); printfflush("Checking records ... "); for(i = 1; i <= 20; i++){ len = sprintf(buf, "%08d", i); if(!(vbuf = crget(curia, buf, len, 0, -1, &vsiz))){ pdperror(name); crclose(curia); return 1; } free(vbuf); if(vsiz != crvsiz(curia, buf, len)){ fprintf(stderr, "%s: %s: invalid vsiz\n", progname, name); crclose(curia); return 1; } } printfflush("ok\n"); printfflush("Closing database ... "); if(!crclose(curia)){ pdperror(name); return 1; } printfflush("ok\n"); printfflush("Creating a database with bnum 1000000 ... "); if(!(curia = cropen(name, DP_OWRITER | DP_OCREAT | DP_OTRUNC, 1000000, -1))){ pdperror(name); return 1; } printfflush("ok\n"); printfflush("Adding 1000 records ... "); for(i = 1; i <= 1000; i++){ len = sprintf(buf, "%08d", i); if(!crput(curia, buf, len, buf, len, DP_DOVER)){ pdperror(name); crclose(curia); return 1; } } printfflush("ok\n"); printfflush("Adding 64 records ... "); for(i = 1; i <= 64; i++){ len = sprintf(buf, "%o", i); if(!crput(curia, buf, len, buf, len, DP_DOVER)){ pdperror(name); crclose(curia); return 1; } } printfflush("ok\n"); printfflush("Syncing the database ... "); if(!crsync(curia)){ pdperror(name); crclose(curia); return 1; } printfflush("ok\n"); printfflush("Retrieving records directly ... "); for(i = 1; i <= 64; i++){ len = sprintf(buf, "%o", i); if(!(vbuf = crsnaffle(name, buf, len, &vsiz))){ pdperror(name); crclose(curia); return 1; } if(strcmp(vbuf, buf)){ fprintf(stderr, "%s: %s: invalid content\n", progname, name); free(vbuf); crclose(curia); return 1; } free(vbuf); if(vsiz != crvsiz(curia, buf, len)){ fprintf(stderr, "%s: %s: invalid vsiz\n", progname, name); crclose(curia); return 1; } } printfflush("ok\n"); printfflush("Optimizing the database ... "); if(!croptimize(curia, -1)){ pdperror(name); crclose(curia); return 1; } printfflush("ok\n"); printfflush("Closing the database ... "); if(!crclose(curia)){ pdperror(name); return 1; } printfflush("ok\n"); printfflush("all ok\n\n"); return 0; } /* perform wicked command */ int dowicked(const char *name, int rnum, int cb){ CURIA *curia; CBMAP *map; int i, len, err, align, mksiz, mvsiz, rsiz; const char *mkbuf, *mvbuf; char buf[RECBUFSIZ], vbuf[RECBUFSIZ], *val; printfflush("\n name=%s rnum=%d\n\n", name, rnum); err = FALSE; if(!(curia = cropen(name, CR_OWRITER | CR_OCREAT | CR_OTRUNC, rnum / 10, 5))){ pdperror(name); return 1; } if(!crsetalign(curia, 16) || !crsetfbpsiz(curia, 256)){ pdperror(name); err = TRUE; } map = NULL; if(cb) map = cbmapopen(); for(i = 1; i <= rnum; i++){ len = sprintf(buf, "%08d", myrand() % rnum + 1); switch(myrand() % 16){ case 0: putchar('O'); if(!crput(curia, buf, len, buf, len, CR_DOVER)) err = TRUE; if(map) cbmapput(map, buf, len, buf, len, TRUE); break; case 1: putchar('K'); if(!crput(curia, buf, len, buf, len, CR_DKEEP) && dpecode != DP_EKEEP) err = TRUE; if(map) cbmapput(map, buf, len, buf, len, FALSE); break; case 2: putchar('D'); if(!crout(curia, buf, len) && dpecode != DP_ENOITEM) err = TRUE; if(map) cbmapout(map, buf, len); break; case 3: putchar('G'); if(crgetwb(curia, buf, len, 2, RECBUFSIZ, vbuf) == -1 && dpecode != DP_ENOITEM) err = TRUE; break; case 4: putchar('V'); if(crvsiz(curia, buf, len) == -1 && dpecode != DP_ENOITEM) err = TRUE; break; default: putchar('C'); if(!crput(curia, buf, len, buf, len, CR_DCAT)) err = TRUE; if(map) cbmapputcat(map, buf, len, buf, len); break; } if(i % 50 == 0) printfflush(" (%08d)\n", i); if(!err && rnum > 100 && myrand() % (rnum / 100) == 0){ if(myrand() % 10 == 0){ align = (myrand() % 4 + 1) * -1; } else { align = myrand() % 32; } if(!crsetalign(curia, align)) err = TRUE; } if(err){ pdperror(name); break; } } if(!croptimize(curia, -1)){ pdperror(name); err = TRUE; } for(i = 1; i <= rnum; i++){ len = sprintf(buf, "%08d", i); if(!crput(curia, buf, len, ":", -1, CR_DCAT)){ pdperror(name); err = TRUE; break; } if(map) cbmapputcat(map, buf, len, ":", -1); putchar(':'); if(i % 50 == 0) printfflush(" (%08d)\n", i); } if(!croptimize(curia, -1)){ pdperror(name); err = TRUE; } for(i = 1; i <= rnum; i++){ len = sprintf(buf, "%08d", i); if(!(val = crget(curia, buf, len, 0, -1, NULL))){ pdperror(name); err = TRUE; break; } free(val); putchar('='); if(i % 50 == 0) printfflush(" (%08d)\n", i); } if(!criterinit(curia)){ pdperror(name); err = TRUE; } for(i = 1; i <= rnum; i++){ if(!(val = criternext(curia, NULL))){ pdperror(name); err = TRUE; break; } free(val); putchar('@'); if(i % 50 == 0) printfflush(" (%08d)\n", i); } if(map){ printfflush("Matching records ... "); cbmapiterinit(map); while((mkbuf = cbmapiternext(map, &mksiz)) != NULL){ mvbuf = cbmapget(map, mkbuf, mksiz, &mvsiz); if(!(val = crget(curia, mkbuf, mksiz, 0, -1, &rsiz))){ pdperror(name); err = TRUE; break; } if(rsiz != mvsiz || memcmp(val, mvbuf, rsiz)){ fprintf(stderr, "%s: %s: unmatched record\n", progname, name); free(val); err = TRUE; break; } free(val); } cbmapclose(map); if(!err) printfflush("ok\n"); } if(!crclose(curia)){ pdperror(name); return 1; } if(!err) printfflush("ok\n\n"); return err ? 1 : 0; } /* END OF FILE */ qdbm-1.8.78/depot.h0000644000175000017500000005436111426320070013034 0ustar mikiomikio/************************************************************************************************* * The basic API of QDBM * Copyright (C) 2000-2007 Mikio Hirabayashi * This file is part of QDBM, Quick Database Manager. * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU * Lesser General Public License as published by the Free Software Foundation; either version * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * You should have received a copy of the GNU Lesser General Public License along with QDBM; if * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. *************************************************************************************************/ #ifndef _DEPOT_H /* duplication check */ #define _DEPOT_H #if defined(__cplusplus) /* export for C++ */ extern "C" { #endif #include #include #if defined(_MSC_VER) && !defined(QDBM_INTERNAL) && !defined(QDBM_STATIC) #define MYEXTERN extern __declspec(dllimport) #else #define MYEXTERN extern #endif /************************************************************************************************* * API *************************************************************************************************/ typedef struct { /* type of structure for a database handle */ char *name; /* name of the database file */ int wmode; /* whether to be writable */ int inode; /* inode of the database file */ time_t mtime; /* last modified time of the database */ int fd; /* file descriptor of the database file */ int fsiz; /* size of the database file */ char *map; /* pointer to the mapped memory */ int msiz; /* size of the mapped memory */ int *buckets; /* pointer to the bucket array */ int bnum; /* number of the bucket array */ int rnum; /* number of records */ int fatal; /* whether a fatal error occured */ int ioff; /* offset of the iterator */ int *fbpool; /* free block pool */ int fbpsiz; /* size of the free block pool */ int fbpinc; /* incrementor of update of the free block pool */ int align; /* basic size of alignment */ } DEPOT; enum { /* enumeration for error codes */ DP_ENOERR, /* no error */ DP_EFATAL, /* with fatal error */ DP_EMODE, /* invalid mode */ DP_EBROKEN, /* broken database file */ DP_EKEEP, /* existing record */ DP_ENOITEM, /* no item found */ DP_EALLOC, /* memory allocation error */ DP_EMAP, /* memory mapping error */ DP_EOPEN, /* open error */ DP_ECLOSE, /* close error */ DP_ETRUNC, /* trunc error */ DP_ESYNC, /* sync error */ DP_ESTAT, /* stat error */ DP_ESEEK, /* seek error */ DP_EREAD, /* read error */ DP_EWRITE, /* write error */ DP_ELOCK, /* lock error */ DP_EUNLINK, /* unlink error */ DP_EMKDIR, /* mkdir error */ DP_ERMDIR, /* rmdir error */ DP_EMISC /* miscellaneous error */ }; enum { /* enumeration for open modes */ DP_OREADER = 1 << 0, /* open as a reader */ DP_OWRITER = 1 << 1, /* open as a writer */ DP_OCREAT = 1 << 2, /* a writer creating */ DP_OTRUNC = 1 << 3, /* a writer truncating */ DP_ONOLCK = 1 << 4, /* open without locking */ DP_OLCKNB = 1 << 5, /* lock without blocking */ DP_OSPARSE = 1 << 6 /* create as a sparse file */ }; enum { /* enumeration for write modes */ DP_DOVER, /* overwrite an existing value */ DP_DKEEP, /* keep an existing value */ DP_DCAT /* concatenate values */ }; /* String containing the version information. */ MYEXTERN const char *dpversion; /* Last happened error code. */ #define dpecode (*dpecodeptr()) /* Get a message string corresponding to an error code. `ecode' specifies an error code. The return value is the message string of the error code. The region of the return value is not writable. */ const char *dperrmsg(int ecode); /* Get a database handle. `name' specifies the name of a database file. `omode' specifies the connection mode: `DP_OWRITER' as a writer, `DP_OREADER' as a reader. If the mode is `DP_OWRITER', the following may be added by bitwise or: `DP_OCREAT', which means it creates a new database if not exist, `DP_OTRUNC', which means it creates a new database regardless if one exists. Both of `DP_OREADER' and `DP_OWRITER' can be added to by bitwise or: `DP_ONOLCK', which means it opens a database file without file locking, or `DP_OLCKNB', which means locking is performed without blocking. `DP_OCREAT' can be added to by bitwise or: `DP_OSPARSE', which means it creates a database file as a sparse file. `bnum' specifies the number of elements of the bucket array. If it is not more than 0, the default value is specified. The size of a bucket array is determined on creating, and can not be changed except for by optimization of the database. Suggested size of a bucket array is about from 0.5 to 4 times of the number of all records to store. The return value is the database handle or `NULL' if it is not successful. While connecting as a writer, an exclusive lock is invoked to the database file. While connecting as a reader, a shared lock is invoked to the database file. The thread blocks until the lock is achieved. If `DP_ONOLCK' is used, the application is responsible for exclusion control. */ DEPOT *dpopen(const char *name, int omode, int bnum); /* Close a database handle. `depot' specifies a database handle. If successful, the return value is true, else, it is false. Because the region of a closed handle is released, it becomes impossible to use the handle. Updating a database is assured to be written when the handle is closed. If a writer opens a database but does not close it appropriately, the database will be broken. */ int dpclose(DEPOT *depot); /* Store a record. `depot' specifies a database handle connected as a writer. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `vbuf' specifies the pointer to the region of a value. `vsiz' specifies the size of the region of the value. If it is negative, the size is assigned with `strlen(vbuf)'. `dmode' specifies behavior when the key overlaps, by the following values: `DP_DOVER', which means the specified value overwrites the existing one, `DP_DKEEP', which means the existing value is kept, `DP_DCAT', which means the specified value is concatenated at the end of the existing value. If successful, the return value is true, else, it is false. */ int dpput(DEPOT *depot, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int dmode); /* Delete a record. `depot' specifies a database handle connected as a writer. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. If successful, the return value is true, else, it is false. False is returned when no record corresponds to the specified key. */ int dpout(DEPOT *depot, const char *kbuf, int ksiz); /* Retrieve a record. `depot' specifies a database handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `start' specifies the offset address of the beginning of the region of the value to be read. `max' specifies the max size to be read. If it is negative, the size to read is unlimited. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the region of the value of the corresponding record, else, it is `NULL'. `NULL' is returned when no record corresponds to the specified key or the size of the value of the corresponding record is less than `start'. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. */ char *dpget(DEPOT *depot, const char *kbuf, int ksiz, int start, int max, int *sp); /* Retrieve a record and write the value into a buffer. `depot' specifies a database handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `start' specifies the offset address of the beginning of the region of the value to be read. `max' specifies the max size to be read. It shuld be equal to or less than the size of the writing buffer. `vbuf' specifies the pointer to a buffer into which the value of the corresponding record is written. If successful, the return value is the size of the written data, else, it is -1. -1 is returned when no record corresponds to the specified key or the size of the value of the corresponding record is less than `start'. Note that no additional zero code is appended at the end of the region of the writing buffer. */ int dpgetwb(DEPOT *depot, const char *kbuf, int ksiz, int start, int max, char *vbuf); /* Get the size of the value of a record. `depot' specifies a database handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. If successful, the return value is the size of the value of the corresponding record, else, it is -1. Because this function does not read the entity of a record, it is faster than `dpget'. */ int dpvsiz(DEPOT *depot, const char *kbuf, int ksiz); /* Initialize the iterator of a database handle. `depot' specifies a database handle. If successful, the return value is true, else, it is false. The iterator is used in order to access the key of every record stored in a database. */ int dpiterinit(DEPOT *depot); /* Get the next key of the iterator. `depot' specifies a database handle. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the region of the next key, else, it is `NULL'. `NULL' is returned when no record is to be get out of the iterator. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. It is possible to access every record by iteration of calling this function. However, it is not assured if updating the database is occurred while the iteration. Besides, the order of this traversal access method is arbitrary, so it is not assured that the order of storing matches the one of the traversal access. */ char *dpiternext(DEPOT *depot, int *sp); /* Set alignment of a database handle. `depot' specifies a database handle connected as a writer. `align' specifies the size of alignment. If successful, the return value is true, else, it is false. If alignment is set to a database, the efficiency of overwriting values is improved. The size of alignment is suggested to be average size of the values of the records to be stored. If alignment is positive, padding whose size is multiple number of the alignment is placed. If alignment is negative, as `vsiz' is the size of a value, the size of padding is calculated with `(vsiz / pow(2, abs(align) - 1))'. Because alignment setting is not saved in a database, you should specify alignment every opening a database. */ int dpsetalign(DEPOT *depot, int align); /* Set the size of the free block pool of a database handle. `depot' specifies a database handle connected as a writer. `size' specifies the size of the free block pool of a database. If successful, the return value is true, else, it is false. The default size of the free block pool is 16. If the size is greater, the space efficiency of overwriting values is improved with the time efficiency sacrificed. */ int dpsetfbpsiz(DEPOT *depot, int size); /* Synchronize updating contents with the file and the device. `depot' specifies a database handle connected as a writer. If successful, the return value is true, else, it is false. This function is useful when another process uses the connected database file. */ int dpsync(DEPOT *depot); /* Optimize a database. `depot' specifies a database handle connected as a writer. `bnum' specifies the number of the elements of the bucket array. If it is not more than 0, the default value is specified. If successful, the return value is true, else, it is false. In an alternating succession of deleting and storing with overwrite or concatenate, dispensable regions accumulate. This function is useful to do away with them. */ int dpoptimize(DEPOT *depot, int bnum); /* Get the name of a database. `depot' specifies a database handle. If successful, the return value is the pointer to the region of the name of the database, else, it is `NULL'. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. */ char *dpname(DEPOT *depot); /* Get the size of a database file. `depot' specifies a database handle. If successful, the return value is the size of the database file, else, it is -1. */ int dpfsiz(DEPOT *depot); /* Get the number of the elements of the bucket array. `depot' specifies a database handle. If successful, the return value is the number of the elements of the bucket array, else, it is -1. */ int dpbnum(DEPOT *depot); /* Get the number of the used elements of the bucket array. `depot' specifies a database handle. If successful, the return value is the number of the used elements of the bucket array, else, it is -1. This function is inefficient because it accesses all elements of the bucket array. */ int dpbusenum(DEPOT *depot); /* Get the number of the records stored in a database. `depot' specifies a database handle. If successful, the return value is the number of the records stored in the database, else, it is -1. */ int dprnum(DEPOT *depot); /* Check whether a database handle is a writer or not. `depot' specifies a database handle. The return value is true if the handle is a writer, false if not. */ int dpwritable(DEPOT *depot); /* Check whether a database has a fatal error or not. `depot' specifies a database handle. The return value is true if the database has a fatal error, false if not. */ int dpfatalerror(DEPOT *depot); /* Get the inode number of a database file. `depot' specifies a database handle. The return value is the inode number of the database file. */ int dpinode(DEPOT *depot); /* Get the last modified time of a database. `depot' specifies a database handle. The return value is the last modified time of the database. */ time_t dpmtime(DEPOT *depot); /* Get the file descriptor of a database file. `depot' specifies a database handle. The return value is the file descriptor of the database file. Handling the file descriptor of a database file directly is not suggested. */ int dpfdesc(DEPOT *depot); /* Remove a database file. `name' specifies the name of a database file. If successful, the return value is true, else, it is false. */ int dpremove(const char *name); /* Repair a broken database file. `name' specifies the name of a database file. If successful, the return value is true, else, it is false. There is no guarantee that all records in a repaired database file correspond to the original or expected state. */ int dprepair(const char *name); /* Dump all records as endian independent data. `depot' specifies a database handle. `name' specifies the name of an output file. If successful, the return value is true, else, it is false. */ int dpexportdb(DEPOT *depot, const char *name); /* Load all records from endian independent data. `depot' specifies a database handle connected as a writer. The database of the handle must be empty. `name' specifies the name of an input file. If successful, the return value is true, else, it is false. */ int dpimportdb(DEPOT *depot, const char *name); /* Retrieve a record directly from a database file. `name' specifies the name of a database file. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the region of the value of the corresponding record, else, it is `NULL'. `NULL' is returned when no record corresponds to the specified key. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. Although this function can be used even while the database file is locked by another process, it is not assured that recent updated is reflected. */ char *dpsnaffle(const char *name, const char *kbuf, int ksiz, int *sp); /* Hash function used inside Depot. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. The return value is the hash value of 31 bits length computed from the key. This function is useful when an application calculates the state of the inside bucket array. */ int dpinnerhash(const char *kbuf, int ksiz); /* Hash function which is independent from the hash functions used inside Depot. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. The return value is the hash value of 31 bits length computed from the key. This function is useful when an application uses its own hash algorithm outside Depot. */ int dpouterhash(const char *kbuf, int ksiz); /* Get a natural prime number not less than a number. `num' specified a natural number. The return value is a natural prime number not less than the specified number. This function is useful when an application determines the size of a bucket array of its own hash algorithm. */ int dpprimenum(int num); /************************************************************************************************* * features for experts *************************************************************************************************/ #define _QDBM_VERSION "1.8.78" #define _QDBM_LIBVER 1414 /* Name of the operating system. */ MYEXTERN const char *dpsysname; /* File descriptor for debugging output. */ MYEXTERN int dpdbgfd; /* Whether this build is reentrant. */ MYEXTERN const int dpisreentrant; /* Set the last happened error code. `ecode' specifies the error code. `line' specifies the number of the line where the error happened. */ void dpecodeset(int ecode, const char *file, int line); /* Get the pointer of the variable of the last happened error code. The return value is the pointer of the variable. */ int *dpecodeptr(void); /* Synchronize updating contents on memory. `depot' specifies a database handle connected as a writer. If successful, the return value is true, else, it is false. */ int dpmemsync(DEPOT *depot); /* Synchronize updating contents on memory, not physically. `depot' specifies a database handle connected as a writer. If successful, the return value is true, else, it is false. */ int dpmemflush(DEPOT *depot); /* Get flags of a database. `depot' specifies a database handle. The return value is the flags of a database. */ int dpgetflags(DEPOT *depot); /* Set flags of a database. `depot' specifies a database handle connected as a writer. `flags' specifies flags to set. Least ten bits are reserved for internal use. If successful, the return value is true, else, it is false. */ int dpsetflags(DEPOT *depot, int flags); #undef MYEXTERN #if defined(__cplusplus) /* export for C++ */ } #endif #endif /* duplication check */ /* END OF FILE */ qdbm-1.8.78/ruby/0000755000175000017500000000000011426320067012526 5ustar mikiomikioqdbm-1.8.78/ruby/rbspex.html0000644000175000017500000002233011426311414014713 0ustar mikiomikio Specifications of QDBM for Ruby

Specifications of QDBM for Ruby

Copyright (C) 2000-2006 Mikio Hirabayashi
Last Update: Thu, 26 Oct 2006 15:00:20 +0900

Table of Contents

  1. Overview
  2. Installation
  3. Examples
  4. Bugs

Overview

QDBM provides API for Ruby. This encapsulates the basic API, the extended API and the advanced API of QDBM. These APIs are safe on multi thread environment of Ruby.

You call the constructor `new' of the class `Depot', `Curia' or `Villa' to open a database file or directory and get the handle. The method `close' is used in order to close the database. Although a finalizer is not used, an iterator of `new' method save you from neglecting to call `close'. The method `put' is used in order to store a record. The method `out' is used in order to delete a record. The method `get' is used in order to retrieve a record. Besides, most operations like ones of the APIs for C are available. Each class has class constants which are `EANY' and its sub classes. They are thrown when each method fails.

Because these classes perform Mix-in of the module `Enumerable', you can use such methods as `find', `sort', and so on. Moreover, they implements such methods: `[]=', `[]', and so on like the class `Hash', you can use a database like a usual hash.

Although keys and values of storing records are treated as strings, binary data can be stored as they are. But, `Villa' can store any serializable and comparable objects. `Depot' realizes a hash database with a file. `Curia' realizes a hash database with a directory and multiple files. `Villa' realizes a B+ tree database with a file. `Depot' is fastest. `Curia' is most scalable. `Villa' provides cursor supporting ordering access.

When `put' overwriting an existing record is cancelled or `get' retrieving a missing record, failure of the operation is noticed by exception. If you dislike such behavior, set the `silent' flag to be true. Then, failure of the operation is noticed by the return value.

For more information about the APIs, read documents in the sub directory `rbapidoc'.


Installation

Make sure that Ruby 1.6.5 or later version is installed and make sure that QDBM is installed under `/usr/local'.

Change the current working directory to the sub directory named `ruby'.

cd ruby

Run the configuration script.

./configure

Build programs.

make

Perform self-diagnostic test.

make check

Install programs. This operation must be carried out by the root user.

make install

When a series of work finishes, `depot.rb', `mod_depot.so', `curia.rb', `mod_curia.so', `villa.rb', `mod_villa.so', and so on are installed under an appropriate directory according to the install directory of Ruby. Executable commands `rbdptest', `rbcrtest', and `rbvltest' will be installed in `/usr/local/bin'.

To uninstall them, execute the following command after `./configure'. This operation must be carried out by the root user.

make uninstall

Examples

The following example stores and retrieves a phone number, using the name as the key.

require 'depot'

NAME = "mikio"
NUMBER = "000-1234-5678"
DBNAME = "book"

def main
  depot = nil
  begin

    # open the database
    depot = Depot::new(DBNAME, Depot::OWRITER | Depot::OCREAT)

    # store the record
    depot.put(NAME, NUMBER)

    # retrieve the record
    printf("Name: %s\n", NAME)
    printf("Number: %s\n", depot.get(NAME))

  rescue Depot::EANY
    printf("%s\n", $!)
    return 1
  ensure

    # close the database
    if(depot)
      begin
        depot.close()
      rescue Depot::EANY
        printf("%s\n", $!)
      end
    end

  end
  return 0
end

exit(main());

The following example is a transcription of the one above, using hash-like interface and iterator.

require 'depot'

NAME = "mikio"
NUMBER = "000-1234-5678"
DBNAME = "book"

def main
  begin

    # open the database and close it automatically
    Depot::new(DBNAME, Depot::OWRITER | Depot::OCREAT) do |depot|

      # store the record
      depot[NAME] = NUMBER

      # retrieve the record
      printf("Name: %s\n", NAME)
      printf("Number: %s\n", depot[NAME])

    end

  rescue Depot::EANY
    printf("%s\n", $!)
    return 1
  end
  return 0
end

exit(main());

The following example performs forward matching search for strings, using the class `Villa'.

require 'villa'

DBNAME = "words"
PREFIX = "apple"

def main
  begin

    # open the database and close it automatically
    Villa::new(DBNAME, Villa::OWRITER | Villa::OCREAT) do |villa|

      # store records
      villa.put("applet", "little application", Villa::DDUP)
      villa.put("aurora", "polar wonderwork", Villa::DDUP)
      villa.put("apple", "delicious fruit", Villa::DDUP)
      villa.put("amigo", "good friend", Villa::DDUP)
      villa.put("apple", "big city", Villa::DDUP)

      begin

        # set the cursor at the top of candidates
        villa.curjump(PREFIX)

        # scan with the cursor
        while(true)
          key = villa.curkey()
          (key.index(PREFIX) == 0) || break
          val = villa.curval()
          printf("%s: %s\n", key, val)
          villa.curnext()
        end

      rescue Villa::ENOITEM
      end

    end

  rescue Villa::EANY
    printf("%s\n", $!)
    return 1
  end
  return 0
end

exit(main());

Bugs

This API are subtly different from the interface of standard library `DBM'.

This API can be implemented more effectively by Ruby hackers.

For the sake of simplicity of interface, Curia for Ruby does not feature handling large objects.


qdbm-1.8.78/ruby/rbapidoc/0000755000175000017500000000000011426320067014311 5ustar mikiomikioqdbm-1.8.78/ruby/rbapidoc/curia.rb.html0000644000175000017500000003714411426320067016715 0ustar mikiomikio curia (QDBM for Ruby)

API of curia


require 'curia'
The library `curia' should be included in application codes. An instance of the class `Curia' is used as a database handle. `Curia' performs Mix-in of `Enumerable'. Each method of `Curia' throws an exception of `Curia::EANY' or its sub classes when an error occurs: `Curia::ENOERR', `Curia::EFATAL', `Curia::EMODE', `Curia::EBROKEN', `Curia::EKEEP', `Curia::ENOITEM', `Curia::EALLOC', `Curia::EMAP', `Curia::EOPEN', `Curia::ECLOSE', `Curia::ETRUNC', `Curia::ESYNC', `Curia::ESTAT', `Curia::ESEEK', `Curia::EREAD', `Curia::EWRITE', `Curia::ELOCK', `Curia::EUNLINK', `Curia::EMKDIR', `Curia::ERMDIR' and `Curia::EMISC'.
curia = Curia::new(name, omode, bnum, dnum)
Constructor: Get a database handle. `name' specifies the name of a database directory. `omode' specifies the connection mode: `Curia::OWRITER' as a writer, `Curia::OREADER' as a reader. If the mode is `Curia::OWRITER', the following may be added by bitwise or: `Curia::OCREAT', which means it creates a new database if not exist, `Curia::OTRUNC', which means it creates a new database regardless if one exists. Both of `Curia::OREADER' and `Curia::OWRITER' can be added to by bitwise or: `Curia::ONOLCK', which means it opens a database directory without file locking, or `Curia::OLCKNB', which means locking is performed without blocking. `Curia::OCREAT' can be added to by bitwise or: `Curia::OSPARSE', which means it creates database files as sparse files. If it is omitted, `Curia::OREADER' is specified. `bnum' specifies the number of elements of the bucket array. If it is omitted or not more than 0, the default value is specified. The size of a bucket array is determined on creating, and can not be changed except for by optimization of the database. Suggested size of a bucket array is about from 0.5 to 4 times of the number of all records to store. `dnum' specifies the number of division of the database. If it is omitted or not more than 0, the default value is specified. The number of division can not be changed from the initial value. The max number of division is 512. The return value is the database handle. An exception of `Curia::EANY' or its sub classes is thrown if an error occurs. If a block parameter is given, this method works as an iterator. A database handle is opened and passed via the first argument of the block. The database handle is surely closed when the block is over. While connecting as a writer, an exclusive lock is invoked to the database directory. While connecting as a reader, a shared lock is invoked to the database directory. The thread blocks until the lock is achieved. If `Curia::ONOLCK' is used, the application is responsible for exclusion control.
curia = Curia::open(name, omode, bnum, dnum)
Constructor: An alias of `new'.
bool = curia.close()
Method: Close the database handle. The return value is always true. An exception of `Curia::EANY' or its sub classes is thrown if an error occurs. Because the region of a closed handle is released, it becomes impossible to use the handle. Updating a database is assured to be written when the handle is closed. If a writer opens a database but does not close it appropriately, the database will be broken.
curia.silent = bool
Method: Set the flag whether to repress frequent exceptions. The return value is the assigned value.
bool = curia.put(key, val, dmode)
Method: Store a record. `key' specifies a key. Although it must be an instance of String, binary data is okey. `val' specifies a value. Although it must be an instance of String, binary data is okey. `dmode' specifies behavior when the key overlaps, by the following values: `Curia::DOVER', which means the specified value overwrites the existing one, `Curia::DKEEP', which means the existing value is kept, `Curia::DCAT', which means the specified value is concatenated at the end of the existing value. If it is omitted, `Curia::DOVER' is specified. The return value is always true. However, if the silent flag is true and replace is cancelled, false is returned instead of exception. An exception of `Curia::EANY' or its sub classes is thrown if an error occurs or replace is cancelled.
bool = curia.store(key, val)
Method: An alias of `put'.
curia[key] = val
Method: An alias of `put'.
bool = curia.out(key)
Method: Delete a record. `key' specifies a key. Although it must be an instance of String, binary data is okey. The return value is always true. However, if the silent flag is true and no record corresponds, false is returned instead of exception. An exception of `Curia::EANY' or its sub classes is thrown if an error occurs or no record corresponds.
bool = curia.delete(key)
Method: An alias of `out'.
bool = curia.clear()
Method: Delete all records. The return value is always true. An exception of `Curia::EANY' or its sub classes is thrown if an error occurs.
str = curia.get(key, start, max)
Method: Retrieve a record. `key' specifies a key. Although it must be an instance of String, binary data is okey. `start' specifies the offset address of the beginning of the region of the value to be read. If it is negative or omitted, the offset is specified as 0. `max' specifies the max size to be read. If it is negative or omitted, the size to read is unlimited. The return value is an instance of the value of the corresponding record. If the silent flag is true and no record corresponds, nil is returned instead of exception. An exception of `Curia::EANY' or its sub classes is thrown if an error occurs, no record corresponds, or the size of the value of the corresponding record is less than `max'.
str = curia.fetch(key, defval)
Method: Retrieve a record. `key' specifies a key. Although it must be an instance of String, binary data is okey. `defval' specifies the default value used when no record corresponds. If it is omitted, nil is specified. The return value is an instance of the value of the corresponding record, or the default value if no record corresponds. An exception of `Curia::EANY' or its sub classes is thrown if an error occurs.
str = curia[key]
Method: An alias of `fetch'.
num = curia.vsiz(key)
Method: Get the size of the value of a record. `key' specifies a key. Although it must be an instance of String, binary data is okey. The return value is the size of the value of the corresponding record. If the silent flag is true and no record corresponds, -1 is returned instead of exception. An exception of `Curia::EANY' or its sub classes is thrown if an error occurs or no record corresponds. Because this method does not read the entity of a record, it is faster than `get'.
bool = curia.iterinit()
Method: Initialize the iterator of the database handle. The return value is always true. An exception of `Curia::EANY' or its sub classes is thrown if an error occurs. The iterator is used in order to access the key of every record stored in a database.
str = curia.iternext()
Method: Get the next key of the iterator. The return value is the value of the next key. If the silent flag is true and no record corresponds, nil is returned instead of exception. An exception of `Curia::EANY' or its sub classes is thrown if an error occurs or no record is to be get out of the iterator. It is possible to access every record by iteration of calling this method. However, it is not assured if updating the database is occurred while the iteration. Besides, the order of this traversal access method is arbitrary, so it is not assured that the order of storing matches the one of the traversal access.
bool = curia.setalign(align)
Method: Set alignment of the database handle. `align' specifies the basic size of alignment. If it is omitted, alignment is cleared. The return value is always true. An exception of `Curia::EANY' or its sub classes is thrown if an error occurs. If alignment is set to a database, the efficiency of overwriting values is improved. The size of alignment is suggested to be average size of the values of the records to be stored. If alignment is positive, padding whose size is multiple number of the alignment is placed. If alignment is negative, as `vsiz' is the size of a value, the size of padding is calculated with `(vsiz / pow(2, abs(align) - 1))'. Because alignment setting is not saved in a database, you should specify alignment every opening a database.
bool = curia.setfbpsiz(size);
Method: Set the size of the free block pool. `size' specifies the size of the free block pool. If it is undef, the free block pool is not used. The return value is always true. An exception of `Curia::EANY' or its sub classes is thrown if an error occurs. The default size of the free block pool is 16. If the size is greater, the space efficiency of overwriting values is improved with the time efficiency sacrificed.
bool = curia.sync()
Method: Synchronize updating contents with the files and the devices. The return value is always true. An exception of `Curia::EANY' or its sub classes is thrown if an error occurs. This method is useful when another process uses the connected database directory.
bool = curia.optimize(bnum)
Method: Optimize the database. `bnum' specifies the number of the elements of the bucket array. If it is omitted or not more than 0, the default value is specified. The return value is always true. An exception of `Curia::EANY' or its sub classes is thrown if an error occurs. In an alternating succession of deleting and storing with overwrite or concatenate, dispensable regions accumulate. This method is useful to do away with them.
num = curia.fsiz()
Method: Get the total size of the database files. The return value is the total size of the database files. An exception of `Curia::EANY' or its sub classes is thrown if an error occurs. If the total size is more than 2GB, the return value overflows.
num = curia.bnum()
Method: Get the total number of the elements of each bucket array. The return value is the total number of the elements of each bucket array An exception of `Curia::EANY' or its sub classes is thrown if an error occurs.
num = curia.rnum()
Method: Get the number of the records stored in the database. The return value is the number of the records stored in the database. An exception of `Curia::EANY' or its sub classes is thrown if an error occurs.
num = curia.length()
Method: An alias of `rnum'.
num = curia.size()
Method: An alias of `rnum'.
bool = curia.writable()
Method: Check whether the database handle is a writer or not. The return value is true if the handle is a writer, false if not. An exception of `Curia::EANY' or its sub classes is thrown if an error occurs.
bool = curia.fatalerror()
Method: Check whether the database has a fatal error or not. The return value is true if the database has a fatal error, false if not. An exception of `Curia::EANY' or its sub classes is thrown if an error occurs.
curia.each() do |key, val| ... end
Iterator Method: Iterate a process with a pair of a key and a value of each record.
curia.each_pair() do |key, val| ... end
Iterator Method: An alias of `each'.
curia.each_key() do |key| ... end
Iterator Method: Iterate a process with a key of each record.
curia.each_value() do |val| ... end
Iterator Method: Iterate a process with a value of each record.
ary = curia.keys()
Method: Get an array of all keys. The return value is an array of all keys. An exception of `Curia::EANY' or its sub classes is thrown if an error occurs.
ary = curia.values()
Method: Get an array of all values. The return value is an array of all values. An exception of `Curia::EANY' or its sub classes is thrown if an error occurs.
str = curia.index(val)
Method: Retrieve a record with a value. `val' specifies a value. Although it must be an instance of String, binary data is okey. The return value is the key of the record with the specified value. An exception of `Curia::EANY' or its sub classes is thrown if an error occurs or no record corresponds. If two or more records correspond, the first found record is selected.
num = curia.to_int()
Method: An alias of `rnum'.
num = curia.to_i()
Method: An alias of `to_int'.
str = curia.to_str()
Method: Get string standing for the instance.
str = curia.to_s()
Method: An alias of `to_str'.
ary = curia.to_ary()
Method: Get an array of alternation of each pair of key and value.
ary = curia.to_a()
Method: An alias of `to_ary'.
hash = curia.to_hash()
Method: Get a hash storing all records.
hash = curia.to_h()
Method: An alias of `to_hash'.
str = curia.inspect()
Method: An alias of `to_str'.

Generated by ./myrbdoc, 2010/08/05.
qdbm-1.8.78/ruby/rbapidoc/villa.rb.html0000644000175000017500000005125211426320067016715 0ustar mikiomikio villa (QDBM for Ruby)

API of villa


require 'villa'
The library `villa' should be included in application codes. An instance of the class `Villa' is used as a database handle. `Villa' performs Mix-in of `Enumerable'. Each method of `Villa' throws an exception of `Villa::EANY' or its sub classes when an error occurs: `Villa::ENOERR', `Villa::EFATAL', `Villa::EMODE', `Villa::EBROKEN', `Villa::EKEEP', `Villa::ENOITEM', `Villa::EALLOC', `Villa::EMAP', `Villa::EOPEN', `Villa::ECLOSE', `Villa::ETRUNC', `Villa::ESYNC', `Villa::ESTAT', `Villa::ESEEK', `Villa::EREAD', `Villa::EWRITE', `Villa::ELOCK', `Villa::EUNLINK', `Villa::EMKDIR', `Villa::ERMDIR' and `Villa::EMISC'.
villa = Villa::new(name, omode, cmode)
Constructor: Get a database handle. `name' specifies the name of a database file. `omode' specifies the connection mode: `Villa::OWRITER' as a writer, `Villa::OREADER' as a reader. If the mode is `Villa::OWRITER', the following may be added by bitwise or: `Villa::OCREAT', which means it creates a new database if not exist, `Villa::OTRUNC', which means it creates a new database regardless if one exists, `Villa::OZCOMP', which means leaves in the database are compressed with ZLIB, `Villa::OYCOMP', which means leaves in the database are compressed with LZO, `Villa::OXCOMP', which means leaves in the database are compressed with BZIP2. Both of `Villa::OREADER' and `Villa::OWRITER' can be added to by bitwise or: `Villa::ONOLCK', which means it opens a database file without file locking, or `Villa::OLCKNB', which means locking is performed without blocking. If it is omitted, `Villa::OREADER' is specified. `cmode' specifies the comparing function: `Villa::CMPLEX' comparing keys in lexical order, `Villa::CMPDEC' comparing keys as decimal strings, `Villa::CMPOBJ' comparing keys as serialized objects implementing the method `<=>'. The comparing function should be kept same in the life of a database. If `Villa::CMPOBJ' is used, such methods as `put', `out', `get' and so on can treat not only instances of `String' but also any serializable and comparable object. If so, objects being stored are serialized and objects being retrieved are deserialized. The return value is the database handle. An exception of `Villa::EANY' or its sub classes is thrown if an error occurs. If a block parameter is given, this method works as an iterator. A database handle is opened and passed via the first argument of the block. The database handle is surely closed when the block is over. While connecting as a writer, an exclusive lock is invoked to the database file. While connecting as a reader, a shared lock is invoked to the database file. The thread blocks until the lock is achieved. `Villa::OZCOMP', `Villa::OYCOMP', and `Villa::OXCOMP' are available only if QDBM was built each with ZLIB, LZO, and BZIP2 enabled. If `Villa::ONOLCK' is used, the application is responsible for exclusion control.
villa = Villa::open(name, omode, cmode)
Constructor: An alias of `new'.
bool = villa.close()
Method: Close the database handle. The return value is always true. An exception of `Villa::EANY' or its sub classes is thrown if an error occurs. Because the region of a closed handle is released, it becomes impossible to use the handle. Updating a database is assured to be written when the handle is closed. If a writer opens a database but does not close it appropriately, the database will be broken. If the transaction is activated and not committed, it is aborted.
villa.silent = bool
Method: Set the flag whether to repress frequent exceptions. The return value is the assigned value.
bool = villa.put(key, val, dmode)
Method: Store a record. `key' specifies a key. Although it must be an instance of String, binary data is okey. `val' specifies a value. Although it must be an instance of String, binary data is okey. `dmode' specifies behavior when the key overlaps, by the following values: `Villa::DOVER', which means the specified value overwrites the existing one, `Villa::DKEEP', which means the existing value is kept, `Villa::DCAT', which means the specified value is concatenated at the end of the existing value, `Villa::DDUP', which means duplication of keys is allowed and the specified value is added as the last one, `Villa::DDUPR', which means duplication of keys is allowed and the specified value is added as the first one. If it is omitted, `Villa::DOVER' is specified. The return value is always true. However, if the silent flag is true and replace is cancelled, false is returned instead of exception. An exception of `Villa::EANY' or its sub classes is thrown if an error occurs or replace is cancelled. The cursor becomes unavailable due to updating database.
bool = villa.store(key, val)
Method: An alias of `put'.
villa[key] = val
Method: An alias of `put'.
bool = villa.out(key)
Method: Delete a record. `key' specifies a key. Although it must be an instance of String, binary data is okey. The return value is always true. However, if the silent flag is true and no record corresponds, false is returned instead of exception. An exception of `Villa::EANY' or its sub classes is thrown if an error occurs or no record corresponds. When the key of duplicated records is specified, the value of the first record of the same key is selected. The cursor becomes unavailable due to updating database.
bool = villa.delete(key)
Method: An alias of `out'.
bool = villa.clear()
Method: Delete all records. The return value is always true. An exception of `Villa::EANY' or its sub classes is thrown if an error occurs.
str = villa.get(key)
Method: Retrieve a record. `key' specifies a key. Although it must be an instance of String, binary data is okey. The return value is an instance of the value of the corresponding record. If the silent flag is true and no record corresponds, nil is returned instead of exception. When the key of duplicated records is specified, the first record of the same key is deleted. An exception of `Villa::EANY' or its sub classes is thrown if an error occurs or no record corresponds.
str = villa.fetch(key, defval)
Method: Retrieve a record. `key' specifies a key. Although it must be an instance of String, binary data is okey. `defval' specifies the default value used when no record corresponds. If it is omitted, nil is specified. The return value is an instance of the value of the corresponding record, or the default value if no record corresponds. An exception of `Villa::EANY' or its sub classes is thrown if an error occurs.
str = villa[key]
Method: An alias of `fetch'.
num = villa.vsiz(key)
Method: Get the size of the value of a record. `key' specifies a key. Although it must be an instance of String, binary data is okey. The return value is the size of the value of the corresponding record. If the silent flag is true and no record corresponds, -1 is returned instead of exception. If multiple records correspond, the size of the first is returned. An exception of `Villa::EANY' or its sub classes is thrown if an error occurs.
num = villa.vnum(key)
Method: Get the number of records corresponding a key. `key' specifies a key. Although it must be an instance of String, binary data is okey. The return value is the size of the value of the corresponding record. If no record corresponds, 0 is returned. An exception of `Villa::EANY' or its sub classes is thrown if an error occurs.
bool = villa.curfirst()
Method: Move the cursor to the first record. The return value is always true. However, if the silent flag is true and no record corresponds, false is returned instead of exception. An exception of `Villa::EANY' or its sub classes is thrown if an error occurs or there is no record in the database.
bool = villa.curlast()
Method: Move the cursor to the last record. The return value is always true. However, if the silent flag is true and no record corresponds, false is returned instead of exception. An exception of `Villa::EANY' or its sub classes is thrown if an error occurs or there is no record in the database.
bool = villa.curprev()
Method: Move the cursor to the previous record. The return value is always true. However, if the silent flag is true and no record corresponds, false is returned instead of exception. An exception of `Villa::EANY' or its sub classes is thrown if an error occurs or there is no previous record.
bool = villa.curnext()
Method: Move the cursor to the next record. The return value is always true. However, if the silent flag is true and no record corresponds, false is returned instead of exception. An exception of `Villa::EANY' or its sub classes is thrown if an error occurs or there is no next record.
bool = villa.curjump(key, jmode)
Method: Move the cursor to a position around a record. `key' specifies a key. Although it must be an instance of String, binary data is okey. `jmode' specifies detail adjustment: `Villa::JFORWARD', which means that the cursor is set to the first record of the same key and that the cursor is set to the next substitute if completely matching record does not exist, `Villa::JBACKWARD', which means that the cursor is set to the last record of the same key and that the cursor is set to the previous substitute if completely matching record does not exist. If it is omitted, `Villa::JFORWARD' is specified. The return value is always true. However, if the silent flag is true and no record corresponds, false is returned instead of exception. An exception of `Villa::EANY' or its sub classes is thrown if an error occurs or there is no record corresponding the condition.
str = villa.curkey()
Method: Get the key of the record where the cursor is. The return value is the key of the corresponding record. If the silent flag is true and no record corresponds, nil is returned instead of exception. An exception of `Villa::EANY' or its sub classes is thrown if an error occurs or no record corresponds to the cursor.
str = villa.curval()
Method: Get the value of the record where the cursor is. The return value is the value of the corresponding record. If the silent flag is true and no record corresponds, nil is returned instead of exception. An exception of `Villa::EANY' or its sub classes is thrown if an error occurs or no record corresponds to the cursor.
bool = villa.curput(val, cpmode);
Method: Insert a record around the cursor. `val' specifies a value. Although it must be an instance of String, binary data is okey. `cpmode' specifies detail adjustment: `Villa::CPCURRENT', which means that the value of the current record is overwritten, `Villa::CPBEFORE', which means that a new record is inserted before the current record, `Villa::CPAFTER', which means that a new record is inserted after the current record. If it is omitted, `Villa::CPCURRENT' is specified. The return value is always true. However, if the silent flag is true and no record corresponds to the cursor, false is returned instead of exception. An exception of `Villa::EANY' or its sub classes is thrown if an error occurs or no record corresponds to the cursor. After insertion, the cursor is moved to the inserted record.
bool = villa.curout();
Method: Delete the record where the cursor is. The return value is always true. However, if the silent flag is true and no record corresponds to the cursor, false is returned instead of exception. An exception of `Villa::EANY' or its sub classes is thrown if an error occurs or no record corresponds to the cursor. After deletion, the cursor is moved to the next record if possible.
bool = villa.settuning(lrecmax, nidxmax, lcnum, ncnum)
Method: Set the tuning parameters for performance. `lrecmax' specifies the max number of records in a leaf node of B+ tree. If it is not more than 0, the default value is specified. `nidxmax' specifies the max number of indexes in a non-leaf node of B+ tree. If it is not more than 0, the default value is specified. `lcnum' specifies the max number of caching leaf nodes. If it is not more than 0, the default value is specified. `ncnum' specifies the max number of caching non-leaf nodes. If it is not more than 0, the default value is specified. The return value is always true. An exception of `Villa::EANY' or its sub classes is thrown if an error occurs. The default setting is equivalent to `vlsettuning(49, 192, 1024, 512)'. Because tuning parameters are not saved in a database, you should specify them every opening a database.
bool = villa.sync()
Method: Synchronize updating contents with the file and the device. The return value is always true. An exception of `Villa::EANY' or its sub classes is thrown if an error occurs. This method is useful when another process uses the connected database file. This method should not be used while the transaction is activated.
bool = villa.optimize()
Method: Optimize the database. The return value is always true. An exception of `Villa::EANY' or its sub classes is thrown if an error occurs. In an alternating succession of deleting and storing with overwrite or concatenate, dispensable regions accumulate. This method is useful to do away with them. This method should not be used while the transaction is activated.
num = villa.fsiz()
Method: Get the size of the database file. The return value is the size of the database file. An exception of `Villa::EANY' or its sub classes is thrown if an error occurs. Because of the I/O buffer, the return value may be less than the real size.
num = villa.rnum()
Method: Get the number of the records stored in the database. The return value is the number of the records stored in the database. An exception of `Villa::EANY' or its sub classes is thrown if an error occurs.
num = villa.length()
Method: An alias of `rnum'.
num = villa.size()
Method: An alias of `rnum'.
bool = villa.writable()
Method: Check whether the database handle is a writer or not. The return value is true if the handle is a writer, false if not. An exception of `Villa::EANY' or its sub classes is thrown if an error occurs.
bool = villa.fatalerror()
Method: Check whether the database has a fatal error or not. The return value is true if the database has a fatal error, false if not. An exception of `Villa::EANY' or its sub classes is thrown if an error occurs.
bool = villa.tranbegin()
Method: Begin the transaction. The return value is always true. An exception of `Villa::EANY' or its sub classes is thrown if an error occurs. If a thread is already in the transaction, the other threads block until the prius is out of the transaction. Only one transaction can be activated with a database handle at the same time.
bool = villa.trancommit()
Method: Commit the transaction. The return value is always true. An exception of `Villa::EANY' or its sub classes is thrown if an error occurs. Updating a database in the transaction is fixed when it is committed successfully. Any other thread except for the one which began the transaction should not call this method.
bool = villa.tranabort()
Method: Abort the transaction. The return value is always true. An exception of `Villa::EANY' or its sub classes is thrown if an error occurs. Updating a database in the transaction is discarded when it is aborted. The state of the database is rollbacked to before transaction. Any other thread except for the one which began the transaction should not call this method.
villa.transaction() do ... end
Iterator Method: Perform an iterator block in the transaction. The specified iterator block is performed in the transaction. If the block returns true, the transaction is committed. If the block returns false or raises any exception, the transaction is aborted.
villa.each() do |key, val| ... end
Iterator Method: Iterate a process with a pair of a key and a value of each record.
villa.each_pair() do |key, val| ... end
Iterator Method: An alias of `each'.
villa.each_key() do |key| ... end
Iterator Method: Iterate a process with a key of each record.
villa.each_value() do |val| ... end
Iterator Method: Iterate a process with a value of each record.
ary = villa.keys()
Method: Get an array of all keys. The return value is an array of all keys. An exception of `Villa::EANY' or its sub classes is thrown if an error occurs.
ary = villa.values()
Method: Get an array of all values. The return value is an array of all values. An exception of `Villa::EANY' or its sub classes is thrown if an error occurs.
str = villa.index(val)
Method: Retrieve a record with a value. `val' specifies a value. Although it must be an instance of String, binary data is okey. The return value is the key of the record with the specified value. An exception of `Villa::EANY' or its sub classes is thrown if an error occurs or no record corresponds. If two or more records correspond, the first found record is selected.
num = villa.to_int()
Method: An alias of `rnum'.
num = villa.to_i()
Method: An alias of `to_int'.
str = villa.to_str()
Method: Get string standing for the instance.
str = villa.to_s()
Method: An alias of `to_str'.
ary = villa.to_ary()
Method: Get an array of alternation of each pair of a key and a value.
ary = villa.to_a()
Method: An alias of `to_ary'.
hash = villa.to_hash()
Method: Get a hash storing all records.
hash = villa.to_h()
Method: An alias of `to_hash'.
str = villa.inspect()
Method: An alias of `to_str'.

Generated by ./myrbdoc, 2010/08/05.
qdbm-1.8.78/ruby/rbapidoc/index.html0000644000175000017500000000671111426320067016313 0ustar mikiomikio INDEX (QDBM for Ruby)
Ruby Source Documents

QDBM for Ruby


Overview

QDBM is a library of routines for managing a database. The database is a simple data file containing records, each is a pair of a key and a value. Every key and value is serial bytes with variable length. Both binary data and character string can be used as a key and a value. There is neither concept of data tables nor data types. Records are organazed in hash table or B+ tree.

As for database of hash table, each key must be unique within a database, so it is impossible to store two or more records with a key overlaps. The following access methods are provided to the database: storing a record with a key and a value, deleting a record by a key, retrieving a record by a key. Moreover, traversal access to every key are provided, although the order is arbitrary. These access methods are similar to ones of DBM (or its followers, NDBM and GDBM) library defined in the UNIX standard. QDBM is an alternative for DBM because of its higher performance.

As for database of B+ tree, records whose keys are duplicated can be stored. Access methods of storing, deleting and retrieving are provided as with the database of hash table. Records are stored in order by a comparing function assigned by a user. It is possible to access each record with the cursor in ascending or descending order. According to this mechanism, forward matching search for strings and range search for integers are realized.

QDBM provides API for Ruby. This encapsulates the basic API, the extended API and the extended API of QDBM. A database handle can be used like an instance of `Hash'.

Refer to `http://fallabs.com/qdbm/' for more information.


API


Generated by ./myrbdoc, 2010/08/05.
qdbm-1.8.78/ruby/rbapidoc/depot.rb.html0000644000175000017500000003640111426320067016720 0ustar mikiomikio depot (QDBM for Ruby)

API of depot


require 'depot'
The library `depot' should be included in application codes. An instance of the class `Depot' is used as a database handle. `Depot' performs Mix-in of `Enumerable'. Each method of `Depot' throws an exception of `Depot::EANY' or its sub classes when an error occurs: `Depot::ENOERR', `Depot::EFATAL', `Depot::EMODE', `Depot::EBROKEN', `Depot::EKEEP', `Depot::ENOITEM', `Depot::EALLOC', `Depot::EMAP', `Depot::EOPEN', `Depot::ECLOSE', `Depot::ETRUNC', `Depot::ESYNC', `Depot::ESTAT', `Depot::ESEEK', `Depot::EREAD', `Depot::EWRITE', `Depot::ELOCK', `Depot::EUNLINK', `Depot::EMKDIR', `Depot::ERMDIR' and `Depot::EMISC'.
depot = Depot::new(name, omode, bnum)
Constructor: Get a database handle. `name' specifies the name of a database file. `omode' specifies the connection mode: `Depot::OWRITER' as a writer, `Depot::OREADER' as a reader. If the mode is `Depot::OWRITER', the following may be added by bitwise or: `Depot::OCREAT', which means it creates a new database if not exist, `Depot::OTRUNC', which means it creates a new database regardless if one exists. Both of `Depot::OREADER' and `Depot::OWRITER' can be added to by bitwise or: `Depot::ONOLCK', which means it opens a database file without file locking, or `Depot::OLCKNB', which means locking is performed without blocking. `Depot::OCREAT' can be added to by bitwise or: `Depot::OSPARSE', which means it creates a database file as a sparse file. If it is omitted, `Depot::OREADER' is specified. `bnum' specifies the number of elements of the bucket array. If it is omitted or not more than 0, the default value is specified. The size of a bucket array is determined on creating, and can not be changed except for by optimization of the database. Suggested size of a bucket array is about from 0.5 to 4 times of the number of all records to store. The return value is the database handle. An exception of `Depot::EANY' or its sub classes is thrown if an error occurs. If a block parameter is given, this method works as an iterator. A database handle is opened and passed via the first argument of the block. The database handle is surely closed when the block is over. While connecting as a writer, an exclusive lock is invoked to the database file. While connecting as a reader, a shared lock is invoked to the database file. The thread blocks until the lock is achieved. If `Depot::ONOLCK' is used, the application is responsible for exclusion control.
depot = Depot::open(name, omode, bnum)
Constructor: An alias of `new'.
bool = depot.close()
Method: Close the database handle. The return value is always true. An exception of `Depot::EANY' or its sub classes is thrown if an error occurs. Because the region of a closed handle is released, it becomes impossible to use the handle. Updating a database is assured to be written when the handle is closed. If a writer opens a database but does not close it appropriately, the database will be broken.
depot.silent = bool
Method: Set the flag whether to repress frequent exceptions. The return value is the assigned value.
bool = depot.put(key, val, dmode)
Method: Store a record. `key' specifies a key. Although it must be an instance of String, binary data is okey. `val' specifies a value. Although it must be an instance of String, binary data is okey. `dmode' specifies behavior when the key overlaps, by the following values: `Depot::DOVER', which means the specified value overwrites the existing one, `Depot::DKEEP', which means the existing value is kept, `Depot::DCAT', which means the specified value is concatenated at the end of the existing value. If it is omitted, `Depot::DOVER' is specified. The return value is always true. However, if the silent flag is true and replace is cancelled, false is returned instead of exception. An exception of `Depot::EANY' or its sub classes is thrown if an error occurs or replace is cancelled.
bool = depot.store(key, val)
Method: An alias of `put'.
depot[key] = val
Method: An alias of `put'.
bool = depot.out(key)
Method: Delete a record. `key' specifies a key. Although it must be an instance of String, binary data is okey. The return value is always true. However, if the silent flag is true and no record corresponds, false is returned instead of exception. An exception of `Depot::EANY' or its sub classes is thrown if an error occurs or no record corresponds.
bool = depot.delete(key)
Method: An alias of `out'.
bool = depot.clear()
Method: Delete all records. The return value is always true. An exception of `Depot::EANY' or its sub classes is thrown if an error occurs.
str = depot.get(key, start, max)
Method: Retrieve a record. `key' specifies a key. Although it must be an instance of String, binary data is okey. `start' specifies the offset address of the beginning of the region of the value to be read. If it is negative or omitted, the offset is specified as 0. `max' specifies the max size to be read. If it is negative or omitted, the size to read is unlimited. The return value is an instance of the value of the corresponding record. If the silent flag is true and no record corresponds, nil is returned instead of exception. An exception of `Depot::EANY' or its sub classes is thrown if an error occurs, no record corresponds, or the size of the value of the corresponding record is less than `max'.
str = depot.fetch(key, defval)
Method: Retrieve a record. `key' specifies a key. Although it must be an instance of String, binary data is okey. `defval' specifies the default value used when no record corresponds. If it is omitted, nil is specified. The return value is an instance of the value of the corresponding record, or the default value if no record corresponds. An exception of `Depot::EANY' or its sub classes is thrown if an error occurs.
str = depot[key]
Method: An alias of `fetch'.
num = depot.vsiz(key)
Method: Get the size of the value of a record. `key' specifies a key. Although it must be an instance of String, binary data is okey. The return value is the size of the value of the corresponding record. If the silent flag is true and no record corresponds, -1 is returned instead of exception. An exception of `Depot::EANY' or its sub classes is thrown if an error occurs or no record corresponds. Because this method does not read the entity of a record, it is faster than `get'.
bool = depot.iterinit()
Method: Initialize the iterator of the database handle. The return value is always true. An exception of `Depot::EANY' or its sub classes is thrown if an error occurs. The iterator is used in order to access the key of every record stored in a database.
str = depot.iternext()
Method: Get the next key of the iterator. The return value is the value of the next key. If the silent flag is true and no record corresponds, nil is returned instead of exception. An exception of `Depot::EANY' or its sub classes is thrown if an error occurs or no record is to be get out of the iterator. It is possible to access every record by iteration of calling this method. However, it is not assured if updating the database is occurred while the iteration. Besides, the order of this traversal access method is arbitrary, so it is not assured that the order of storing matches the one of the traversal access.
bool = depot.setalign(align)
Method: Set alignment of the database handle. `align' specifies the basic size of alignment. If it is omitted, alignment is cleared. The return value is always true. An exception of `Depot::EANY' or its sub classes is thrown if an error occurs. If alignment is set to a database, the efficiency of overwriting values is improved. The size of alignment is suggested to be average size of the values of the records to be stored. If alignment is positive, padding whose size is multiple number of the alignment is placed. If alignment is negative, as `vsiz' is the size of a value, the size of padding is calculated with `(vsiz / pow(2, abs(align) - 1))'. Because alignment setting is not saved in a database, you should specify alignment every opening a database.
bool = depot.setfbpsiz(size);
Method: Set the size of the free block pool. `size' specifies the size of the free block pool. If it is undef, the free block pool is not used. The return value is always true. An exception of `Depot::EANY' or its sub classes is thrown if an error occurs. The default size of the free block pool is 16. If the size is greater, the space efficiency of overwriting values is improved with the time efficiency sacrificed.
bool = depot.sync()
Method: Synchronize updating contents with the file and the device. The return value is always true. An exception of `Depot::EANY' or its sub classes is thrown if an error occurs. This method is useful when another process uses the connected database file.
bool = depot.optimize(bnum)
Method: Optimize the database. `bnum' specifies the number of the elements of the bucket array. If it is omitted or not more than 0, the default value is specified. The return value is always true. An exception of `Depot::EANY' or its sub classes is thrown if an error occurs. In an alternating succession of deleting and storing with overwrite or concatenate, dispensable regions accumulate. This method is useful to do away with them.
num = depot.fsiz()
Method: Get the size of the database file. The return value is the size of the database file. An exception of `Depot::EANY' or its sub classes is thrown if an error occurs.
num = depot.bnum()
Method: Get the number of the elements of the bucket array. The return value is the number of the elements of the bucket array An exception of `Depot::EANY' or its sub classes is thrown if an error occurs.
num = depot.rnum()
Method: Get the number of the records stored in the database. The return value is the number of the records stored in the database. An exception of `Depot::EANY' or its sub classes is thrown if an error occurs.
num = depot.length()
Method: An alias of `rnum'.
num = depot.size()
Method: An alias of `rnum'.
bool = depot.writable()
Method: Check whether the database handle is a writer or not. The return value is true if the handle is a writer, false if not. An exception of `Depot::EANY' or its sub classes is thrown if an error occurs.
bool = depot.fatalerror()
Method: Check whether the database has a fatal error or not. The return value is true if the database has a fatal error, false if not. An exception of `Depot::EANY' or its sub classes is thrown if an error occurs.
depot.each() do |key, val| ... end
Iterator Method: Iterate a process with a pair of a key and a value of each record.
depot.each_pair() do |key, val| ... end
Iterator Method: An alias of `each'.
depot.each_key() do |key| ... end
Iterator Method: Iterate a process with a key of each record.
depot.each_value() do |val| ... end
Iterator Method: Iterate a process with a value of each record.
ary = depot.keys()
Method: Get an array of all keys. The return value is an array of all keys. An exception of `Depot::EANY' or its sub classes is thrown if an error occurs.
ary = depot.values()
Method: Get an array of all values. The return value is an array of all values. An exception of `Depot::EANY' or its sub classes is thrown if an error occurs.
str = depot.index(val)
Method: Retrieve a record with a value. `val' specifies a value. Although it must be an instance of String, binary data is okey. The return value is the key of the record with the specified value. An exception of `Depot::EANY' or its sub classes is thrown if an error occurs or no record corresponds. If two or more records correspond, the first found record is selected.
num = depot.to_int()
Method: An alias of `rnum'.
num = depot.to_i()
Method: An alias of `to_int'.
str = depot.to_str()
Method: Get string standing for the instance.
str = depot.to_s()
Method: An alias of `to_str'.
ary = depot.to_ary()
Method: Get an array of alternation of each pair of a key and a value.
ary = depot.to_a()
Method: An alias of `to_ary'.
hash = depot.to_hash()
Method: Get a hash storing all records.
hash = depot.to_h()
Method: An alias of `to_hash'.
str = depot.inspect()
Method: An alias of `to_str'.

Generated by ./myrbdoc, 2010/08/05.
qdbm-1.8.78/ruby/Makefile.in0000644000175000017500000000732510477441175014613 0ustar mikiomikio# Makefile for Ruby interface of QDBM #================================================================ # Setting variables #================================================================ # Generic settings SHELL = @SHELL@ # Packaging PACKAGE = qdbm # Targets MYBINS = depot/rbdptest curia/rbcrtest villa/rbvltest MYDOCS = rbspex.html rbspex-ja.html rbapidoc # Install destinations prefix = @prefix@ exec_prefix = @exec_prefix@ MYBINDIR = @bindir@ MYDATADIR = @datadir@/$(PACKAGE)/ruby DESTDIR = # Building binaries RUNENV = LD_LIBRARY_PATH=.:..:../..:/usr/local/lib #================================================================ # Actions #================================================================ all : cd depot && [ -f Makefile ] || $(RUNENV) ruby extconf.rb ; $(RUNENV) make cd curia && [ -f Makefile ] || $(RUNENV) ruby extconf.rb ; $(RUNENV) make cd villa && [ -f Makefile ] || $(RUNENV) ruby extconf.rb ; $(RUNENV) make @printf '\n' @printf '#================================================================\n' @printf '# Ready to install.\n' @printf '#================================================================\n' clean : cd depot ; if [ -f Makefile ] ; then $(RUNENV) make -i clean ; fi || true cd depot ; rm -rf Makefile *.o *.so *.log casket *~ cd curia ; if [ -f Makefile ] ; then $(RUNENV) make -i clean ; fi || true cd curia ; rm -rf Makefile *.o *.so *.log casket *~ cd villa ; if [ -f Makefile ] ; then $(RUNENV) make -i clean ; fi || true cd villa ; rm -rf Makefile *.o *.so *.log casket *~ rm -rf casket *~ install : cd depot ; make install cd curia ; make install cd villa ; make install mkdir -p $(DESTDIR)$(MYBINDIR) cp -f $(MYBINS) $(DESTDIR)$(MYBINDIR) mkdir -p $(DESTDIR)$(MYDATADIR) cp -Rf $(MYDOCS) $(DESTDIR)$(MYDATADIR) @printf '\n' @printf '#================================================================\n' @printf '# Thanks for using QDBM for Ruby.\n' @printf '#================================================================\n' uninstall : pprefix=`ruby -e '$$:.each() do |path| ; printf("%s\n", path) ; end' | grep -v '^\.'` ; \ find $$pprefix -print | sort | uniq | \ egrep '(mod_depot\.so|depot\.rb|mod_curia\.so|curia\.rb|mod_villa\.so|villa\.rb)' | \ xargs rm -f for file in $(MYBINS) ; \ do \ file=`printf '%s' $$file | sed 's/.*\///'` ; \ rm -f "$(DESTDIR)$(MYBINDIR)/$$file" ; \ done rm -rf $(DESTDIR)$(MYDATADIR) check : sync ; sync cd depot && rm -rf casket cd depot && \ $(RUNENV) ruby -w -Ilib rbdptest write casket 10000 1000 cd depot && \ $(RUNENV) ruby -w -Ilib rbdptest read casket cd depot && \ $(RUNENV) ruby -w -Ilib rbdptest misc casket cd depot && rm -rf casket cd curia && rm -rf casket cd curia && \ $(RUNENV) ruby -w -Ilib rbcrtest write casket 10000 1000 10 cd curia && \ $(RUNENV) ruby -w -Ilib rbcrtest read casket cd curia && \ $(RUNENV) ruby -w -Ilib rbcrtest misc casket cd curia && rm -rf casket cd villa && rm -rf casket cd villa && \ $(RUNENV) ruby -w -Ilib rbvltest write casket 10000 cd villa && \ $(RUNENV) ruby -w -Ilib rbvltest read casket cd villa && \ $(RUNENV) ruby -w -Ilib rbvltest misc casket cd villa && rm -rf casket @printf '\n' @printf '#================================================================\n' @printf '# Checking completed.\n' @printf '#================================================================\n' doc : make docclean $(RUNENV) ./myrbdoc -d rbapidoc -t "QDBM for Ruby" -a overview \ depot/lib/depot.rb curia/lib/curia.rb villa/lib/villa.rb docclean : rm -rf rbapidoc dist : make doc make distclean distclean : clean rm -rf Makefile config.cache config.log config.status autom4te.cache .PHONY : all clean install check # END OF FILE qdbm-1.8.78/ruby/overview0000644000175000017500000000330411426314356014323 0ustar mikiomikio

Overview

QDBM is a library of routines for managing a database. The database is a simple data file containing records, each is a pair of a key and a value. Every key and value is serial bytes with variable length. Both binary data and character string can be used as a key and a value. There is neither concept of data tables nor data types. Records are organazed in hash table or B+ tree.

As for database of hash table, each key must be unique within a database, so it is impossible to store two or more records with a key overlaps. The following access methods are provided to the database: storing a record with a key and a value, deleting a record by a key, retrieving a record by a key. Moreover, traversal access to every key are provided, although the order is arbitrary. These access methods are similar to ones of DBM (or its followers, NDBM and GDBM) library defined in the UNIX standard. QDBM is an alternative for DBM because of its higher performance.

As for database of B+ tree, records whose keys are duplicated can be stored. Access methods of storing, deleting and retrieving are provided as with the database of hash table. Records are stored in order by a comparing function assigned by a user. It is possible to access each record with the cursor in ascending or descending order. According to this mechanism, forward matching search for strings and range search for integers are realized.

QDBM provides API for Ruby. This encapsulates the basic API, the extended API and the extended API of QDBM. A database handle can be used like an instance of `Hash'.

Refer to `http://fallabs.com/qdbm/' for more information.

qdbm-1.8.78/ruby/myrbdoc0000755000175000017500000001275111426315247014125 0ustar mikiomikio#! /usr/bin/ruby -w #================================================================ # myrbdoc # Document generator for Ruby sources #================================================================ # main routine def main files = [] err = false destdir = nil ptitle = "Ruby API" afile = nil i = 0 while(i < ARGV.length) if(files.length < 1 && ARGV[i] =~ /^-/) if(ARGV[i] == "-d") destdir = ARGV[i+=1] elsif(ARGV[i] == "-t") ptitle = ARGV[i+=1] elsif(ARGV[i] == "-a") afile = ARGV[i+=1] else usage() end else files.push(ARGV[i]) end i += 1 end (files.length > 0) || usage() (destdir) || (destdir = ".") (File::directory?(destdir)) || Dir::mkdir(destdir) files.each() do |file| makedoc(destdir, ptitle, file) end makeindex(destdir, ptitle, afile, files) return 0 end # print the usage and exit def usage printf(STDERR, "%s: usage: %s: [-d dir] [-t str] [-a file] file ...\n", $0, $0) exit(1) end # generate a document def makedoc(destdir, ptitle, name) source = name.gsub(/.*\//, "") dest = sprintf("%s/%s.html", destdir, source) File::open(name, "r") do |infile| File::open(dest, "w") do |outfile| writehead(outfile, ptitle, source) while(line = infile.gets()) line.chomp!() line.gsub!(/^ */, "") if(line =~ /^\x23\x23/) group = Array::new() while(line = infile.gets()) line.chomp!() line.gsub!(/^ */, "") (line =~ /^\x23[^@]/) || break (line.length() > 1) || next group.push(line) end if(group.length() > 1) printf(outfile, "
\n") kbd = group[0] =~ /^\x23:/ group.each() do |elem| elem.gsub!(/^\x23[ :]*/, "") elem.gsub!(/&/, "&") elem.gsub!(//, ">") elem.gsub!(/\x22/, """) end if(kbd) printf(outfile, "
%s
\n", group[0]) else printf(outfile, "
%s
\n", group[0]) end group.shift() if(group.length > 0) printf(outfile, "
\n") group.each() do |elem| printf(outfile, "%s\n", elem) end printf(outfile, "
\n") end printf(outfile, "
\n") end end end printf(outfile, "
\n") writetail(outfile) end end end # generate the index file def makeindex(destdir, ptitle, afile, files) dest = sprintf("%s/index.html", destdir) File::open(dest, "w") do |outfile| writehead(outfile, ptitle) if(afile) File::open(afile, "r") do |infile| while(line = infile.gets()) line.chomp!() printf(outfile, "%s\n", line) end end printf(outfile, "
\n") end printf(outfile, "

API

\n") printf(outfile, "
    \n") files.each() do |file| file = file.gsub(/.*\//, "") printf(outfile, "
  • %s
  • \n", file, file.gsub(/\..*/, "")) end printf(outfile, "
\n") printf(outfile, "
\n") writetail(outfile) end end # write header def writehead(outfile, ptitle, name = nil) if(name) title = sprintf("%s (%s)", name.gsub(/\..*/, ""), ptitle) head = sprintf("API of %s", name.gsub(/\..*/, "")) navi = "" else title = sprintf("INDEX (%s)", ptitle) head = ptitle navi = "
Ruby Source Documents
" end printf(outfile, "%s", <<__MYEOF) #{title} #{navi}

#{head}


__MYEOF end # write tail def writetail(outfile) (sec, min, hour, mday, mon, year) = Time::now.to_a datestr = sprintf("%04d/%02d/%02d", year, mon, mday) printf(outfile, "%s", <<__MYEOF)
Generated by #{$0}, #{datestr}.
__MYEOF end # execute main #$0.gsub!(/.*\//, "") exit(main()) # END OF FILE qdbm-1.8.78/ruby/configure.in0000644000175000017500000000216710443467461015055 0ustar mikiomikio# Source of configuration for Ruby interface of QDBM # Targets AC_INIT(qdbm-ruby, 1.0.0) # Building paths pathtmp="$PATH" PATH="$HOME/bin:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin" PATH="$PATH:/usr/ccs/bin:/usr/ucb:/usr/xpg4/bin:/usr/xpg6/bin:$pathtmp" LIBRARY_PATH="$HOME/lib:/usr/local/lib:$LIBRARY_PATH" LD_LIBRARY_PATH="$HOME/lib:/usr/local/lib:$LD_LIBRARY_PATH" CPATH="$HOME/include:/usr/local/include:$CPATH" export PATH LIBRARY_PATH LD_LIBRARY_PATH CPATH # Setting the default prefix if test "$prefix" = NONE then prefix=`ruby -rrbconfig -e 'puts(Config::CONFIG.fetch("prefix"))'` fi # Duplication of QDBM for Ruby AC_CHECK_LIB(qdbm, main, true, printf 'checking whether /usr/local/lib/libqdbm.* is... ' if ls /usr/local/lib/libqdbm.* > /dev/null 2>&1 then printf 'yes\n' else printf 'no\n' printf '#================================================================\n' 1>&2 printf '# WARNING: Install QDBM libraries before installation.\n' 1>&2 printf '#================================================================\n' 1>&2 fi ) # Targets AC_OUTPUT(Makefile) # END OF FILE qdbm-1.8.78/ruby/curia/0000755000175000017500000000000010705266455013642 5ustar mikiomikioqdbm-1.8.78/ruby/curia/MANIFEST0000644000175000017500000000006207727054646015000 0ustar mikiomikioMANIFEST extconf.rb curia.rb mod_curia.c rbcrtest qdbm-1.8.78/ruby/curia/rbcrtest0000755000175000017500000001514610505767567015437 0ustar mikiomikio#! /usr/bin/ruby -w #================================================================================================= # Test cases of Curia for Ruby # Copyright (C) 2000-2005 Mikio Hirabayashi # This file is part of QDBM, Quick Database Manager. # QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU # Lesser General Public License as published by the Free Software Foundation; either version # 2.1 of the License or any later version. QDBM is distributed in the hope that it will be # useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more # details. # You should have received a copy of the GNU Lesser General Public License along with QDBM; if # not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA # 02111-1307 USA. #================================================================================================= require 'curia' # main routine def main() $0.gsub!(/.*\//, "") (ARGV.length >= 1) || usage() if(ARGV[0] == "write") rv = runwrite() elsif(ARGV[0] == "read") rv = runread() elsif(ARGV[0] == "misc") rv = runmisc() else usage() end return rv end # print the usage and exit def usage() printf(STDERR, "%s: test cases for Curia for Ruby\n", $0) printf(STDERR, "\n") printf(STDERR, "usage:\n") printf(STDERR, " %s write name rnum bnum dnum\n", $0) printf(STDERR, " %s read name\n", $0) printf(STDERR, " %s misc name\n", $0) printf(STDERR, "\n") exit(1) end # parse arguments of write command def runwrite() name = nil rnum = -1 bnum = -1 dnum = -1 i = 1 while(i < ARGV.length) if(!name && ARGV[i] =~ /^-/) usage() elsif(!name) name = ARGV[i] elsif(rnum < 0) rnum = ARGV[i].to_i() elsif(bnum < 0) bnum = ARGV[i].to_i() elsif(dnum < 0) dnum = ARGV[i].to_i() else usage() end i += 1 end (name && rnum > 0 && bnum > 0 && dnum > 0) || usage() dowrite(name, rnum, bnum, dnum) return 0 end # parse arguments of read command def runread() name = nil i = 1 while(i < ARGV.length) if(!name && ARGV[i] =~ /^-/) usage() elsif(!name) name = ARGV[i] else usage() end i += 1 end (name) || usage() doread(name) return 0 end # parse arguments of misc command def runmisc() name = nil i = 1 while(i < ARGV.length) if(!name && ARGV[i] =~ /^-/) usage() elsif(!name) name = ARGV[i] else usage() end i += 1 end (name) || usage() domisc(name) return 0 end # perform write command def dowrite(name, rnum, bnum, dnum) printf("\n name=%s rnum=%d bnum=%d dnum=%d\n\n", name, rnum, bnum, dnum) curia = nil begin # open a database curia = Curia::new(name, Curia::OWRITER | Curia::OCREAT | Curia::OTRUNC, bnum, dnum) # loop for each record STDOUT.sync = true 1.upto(rnum) do |i| buf = sprintf("%08d", i) # store a record curia.put(buf, buf) # print progression if(rnum > 250 && i % (rnum / 250) == 0) print(".") if(i == rnum || i % (rnum / 10) == 0) printf(" (%08d)\n", i) end end end rescue printf("%s: %s: %s\n", $0, name, $!) return 1 ensure begin # close the database (curia) && curia.close() rescue return 1 end end printf("ok\n\n") return 0 end # perform read command def doread(name) printf("\n name=%s\n\n", name) curia = nil begin # open a database curia = Curia::new(name) # get the number of record rnum = curia.rnum() # loop for each record STDOUT.sync = true 1.upto(rnum) do |i| buf = sprintf("%08d", i) # store a record curia.get(buf) # print progression if(rnum > 250 && i % (rnum / 250) == 0) print(".") if(i == rnum || i % (rnum / 10) == 0) printf(" (%08d)\n", i) end end end rescue printf("%s: %s: %s\n", $0, name, $!) return 1 ensure begin # close the database (curia) && curia.close() rescue return 1 end end printf("ok\n\n") return 0 end # perform misc command def domisc(name) loopnum = 500 bucketnum = 16 divnum = 3 threadnum = 10 printf("\n name=%s\n\n", name) curia = nil begin # open the database printf("Creating a database ... ") curia = Curia::open("casket", Curia::OWRITER | Curia::OCREAT | Curia::OTRUNC, bucketnum, divnum) printf("ok\n") # store records printf("Storing records ... ") 1.upto(loopnum) do |i| buf = sprintf("%08d", i) curia[buf] = buf end printf("ok\n") # retrieve records printf("Retrieving records ... ") 1.upto(loopnum) do |i| buf = sprintf("%08d", i) (curia[buf] == buf) || raise("key and value does not match") end printf("ok\n") # traverse records printf("Traversing records ... ") curia.each() do |key, val| (key == val) || raise("key and value does not match") end curia.keys() curia.values() printf("ok\n") # silent mode operations printf("Silent mode operations ... ") curia.silent = true curia.put("foo", "bar", Curia::DKEEP) curia.put("foo", "bar", Curia::DKEEP) curia.get("foo") curia.out("foo") curia.out("foo") curia.get("nil") curia.fetch("nil", "void"); curia.keys() curia.values() printf("ok\n") rescue printf("%s: %s: %s\n", $0, name, $!) return 1 ensure # close the database printf("Closing the database ... ") (curia) && curia.close() printf("ok\n") end # test iterator and threads printf("Processing with iterator and threads ... ") Curia::new("casket", Curia::OWRITER) do |curia| (curia.rnum() == loopnum) || raise("record number is invalid") curia.clear() threads = [] 1.upto(threadnum) do |i| t = Thread::new() do 1.upto(loopnum) do |j| buf = sprintf("%08d", j) curia.put(buf, "*", Curia::DCAT) end end threads.push(t) end threads.each do |t| t.join() end 1.upto(loopnum) do |i| buf = sprintf("%08d", i) (curia.vsiz(buf) == threadnum) || raise("thread writing is invalid") end (curia.index("*" * threadnum)) || raise("thread writing is invalid") end printf("ok\n") printf("all ok\n\n") return 0 end # execute main $0.gsub!(/.*\//, "") exit(main()) # END OF FILE qdbm-1.8.78/ruby/curia/extconf.rb0000644000175000017500000000070310363125124015620 0ustar mikiomikiorequire 'mkmf' dir_config("curia") home = ENV['HOME'] $CFLAGS = "-I. -I../.. -I#{home}/include -I/usr/local/include" $LDFLAGS = "-L../.. -L#{home}/lib -L/usr/local/lib" $LIBS = "-L../.. -L#{home}/lib -L/usr/local/lib" have_library("c", "main") have_library("pthread", "main") have_library("z", "main") have_library("bz2", "main") have_library("lzo2", "main") have_library("iconv", "main") have_library("qdbm", "main") create_makefile("mod_curia") qdbm-1.8.78/ruby/curia/lib/0000755000175000017500000000000010505770173014403 5ustar mikiomikioqdbm-1.8.78/ruby/curia/lib/curia.rb0000644000175000017500000004711410505767470016050 0ustar mikiomikio#================================================================================================= # Ruby API of Curia, the basic API of QDBM # Copyright (C) 2000-2006 Mikio Hirabayashi # This file is part of QDBM, Quick Database Manager. # QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU # Lesser General Public License as published by the Free Software Foundation; either version # 2.1 of the License or any later version. QDBM is distributed in the hope that it will be # useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more # details. # You should have received a copy of the GNU Lesser General Public License along with QDBM; if # not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA # 02111-1307 USA. #================================================================================================= require 'mod_curia' require 'thread' ## # require 'curia' # The library `curia' should be included in application codes. # An instance of the class `Curia' is used as a database handle. # `Curia' performs Mix-in of `Enumerable'. # Each method of `Curia' throws an exception of `Curia::EANY' or its sub classes when an error # occurs: `Curia::ENOERR', `Curia::EFATAL', `Curia::EMODE', `Curia::EBROKEN', `Curia::EKEEP', # `Curia::ENOITEM', `Curia::EALLOC', `Curia::EMAP', `Curia::EOPEN', `Curia::ECLOSE', # `Curia::ETRUNC', `Curia::ESYNC', `Curia::ESTAT', `Curia::ESEEK', `Curia::EREAD', # `Curia::EWRITE', `Curia::ELOCK', `Curia::EUNLINK', `Curia::EMKDIR', `Curia::ERMDIR' and # `Curia::EMISC'. # class Curia include Mod_Curia, Enumerable #---------------------------------------------------------------- # class constants #---------------------------------------------------------------- MyMutex = Mutex::new() #---------------------------------------------------------------- # class methods #---------------------------------------------------------------- public ## # curia = Curia::new(name, omode, bnum, dnum) # Constructor: Get a database handle. # `name' specifies the name of a database directory. # `omode' specifies the connection mode: `Curia::OWRITER' as a writer, `Curia::OREADER' as a # reader. If the mode is `Curia::OWRITER', the following may be added by bitwise or: # `Curia::OCREAT', which means it creates a new database if not exist, `Curia::OTRUNC', which # means it creates a new database regardless if one exists. Both of `Curia::OREADER' and # `Curia::OWRITER' can be added to by bitwise or: `Curia::ONOLCK', which means it opens a # database directory without file locking, or `Curia::OLCKNB', which means locking is # performed without blocking. `Curia::OCREAT' can be added to by bitwise or: `Curia::OSPARSE', # which means it creates database files as sparse files. If it is omitted, `Curia::OREADER' # is specified. # `bnum' specifies the number of elements of the bucket array. If it is omitted or not more # than 0, the default value is specified. The size of a bucket array is determined on # creating, and can not be changed except for by optimization of the database. Suggested # size of a bucket array is about from 0.5 to 4 times of the number of all records to store. # `dnum' specifies the number of division of the database. If it is omitted or not more than # 0, the default value is specified. The number of division can not be changed from the # initial value. The max number of division is 512. # The return value is the database handle. # An exception of `Curia::EANY' or its sub classes is thrown if an error occurs. # If a block parameter is given, this method works as an iterator. A database handle is # opened and passed via the first argument of the block. The database handle is surely # closed when the block is over. # While connecting as a writer, an exclusive lock is invoked to the database directory. # While connecting as a reader, a shared lock is invoked to the database directory. The thread # blocks until the lock is achieved. If `Curia::ONOLCK' is used, the application is # responsible for exclusion control. # #@ DEFINED IMPLICITLY ## # curia = Curia::open(name, omode, bnum, dnum) # Constructor: An alias of `new'. # #@ DEFINED OUTSIDE #---------------------------------------------------------------- # private methods #---------------------------------------------------------------- private #= # initialize(name, omode, bnum) # Method: Called implicitly by the constructor. # def initialize(name, omode = OREADER, bnum = -1, dnum = -1) @silent = false MyMutex.synchronize() do @index = mod_open(name, omode, bnum, dnum) @name = name end if(iterator?) begin yield(self) ensure close() end end self end #= # clone() # Method: Forbidden to use. # def clone raise(CuriaError) end #= # dup() # Method: Forbidden to use. # alias dup clone #---------------------------------------------------------------- # public methods #---------------------------------------------------------------- public ## # bool = curia.close() # Method: Close the database handle. # The return value is always true. # An exception of `Curia::EANY' or its sub classes is thrown if an error occurs. # Because the region of a closed handle is released, it becomes impossible to use the handle. # Updating a database is assured to be written when the handle is closed. If a writer opens # a database but does not close it appropriately, the database will be broken. # def close() MyMutex.synchronize() do begin mod_close(@index) ensure @index = -1 end end end ## # curia.silent = bool # Method: Set the flag whether to repress frequent exceptions. # The return value is the assigned value. # def silent=(value) @silent = value ? true : false mod_setsilent(@index, silent ? 1 : 0) @silent end def silent @silent end ## # bool = curia.put(key, val, dmode) # Method: Store a record. # `key' specifies a key. Although it must be an instance of String, binary data is okey. # `val' specifies a value. Although it must be an instance of String, binary data is okey. # `dmode' specifies behavior when the key overlaps, by the following values: `Curia::DOVER', # which means the specified value overwrites the existing one, `Curia::DKEEP', which means # the existing value is kept, `Curia::DCAT', which means the specified value is concatenated # at the end of the existing value. If it is omitted, `Curia::DOVER' is specified. # The return value is always true. However, if the silent flag is true and replace is # cancelled, false is returned instead of exception. # An exception of `Curia::EANY' or its sub classes is thrown if an error occurs or replace # is cancelled. # def put(key, val, dmode = DOVER) mod_put(@index, key, val, dmode) end ## # bool = curia.store(key, val) # Method: An alias of `put'. # alias store put ## # curia[key] = val # Method: An alias of `put'. # alias []= put ## # bool = curia.out(key) # Method: Delete a record. # `key' specifies a key. Although it must be an instance of String, binary data is okey. # The return value is always true. However, if the silent flag is true and no record # corresponds, false is returned instead of exception. # An exception of `Curia::EANY' or its sub classes is thrown if an error occurs or no record # corresponds. # def out(key) mod_out(@index, key) end ## # bool = curia.delete(key) # Method: An alias of `out'. # alias delete out ## # bool = curia.clear() # Method: Delete all records. # The return value is always true. # An exception of `Curia::EANY' or its sub classes is thrown if an error occurs. # def clear MyMutex.synchronize() do iterinit() while(rnum() > 0) out(iternext()) end end true end ## # str = curia.get(key, start, max) # Method: Retrieve a record. # `key' specifies a key. Although it must be an instance of String, binary data is okey. # `start' specifies the offset address of the beginning of the region of the value to be read. # If it is negative or omitted, the offset is specified as 0. # `max' specifies the max size to be read. If it is negative or omitted, the size to read is # unlimited. # The return value is an instance of the value of the corresponding record. If the silent flag # is true and no record corresponds, nil is returned instead of exception. # An exception of `Curia::EANY' or its sub classes is thrown if an error occurs, no record # corresponds, or the size of the value of the corresponding record is less than `max'. # def get(key, start = 0, max = -1) mod_get(@index, key, start, max) end ## # str = curia.fetch(key, defval) # Method: Retrieve a record. # `key' specifies a key. Although it must be an instance of String, binary data is okey. # `defval' specifies the default value used when no record corresponds. If it is omitted, nil # is specified. # The return value is an instance of the value of the corresponding record, or the default # value if no record corresponds. # An exception of `Curia::EANY' or its sub classes is thrown if an error occurs. # def fetch(key, defval = nil) if @silent if val = mod_get(@index, key, 0, -1) val else defval end else begin mod_get(@index, key, 0, -1) rescue ENOITEM defval end end end ## # str = curia[key] # Method: An alias of `fetch'. # alias [] fetch ## # num = curia.vsiz(key) # Method: Get the size of the value of a record. # `key' specifies a key. Although it must be an instance of String, binary data is okey. # The return value is the size of the value of the corresponding record. If the silent flag # is true and no record corresponds, -1 is returned instead of exception. # An exception of `Curia::EANY' or its sub classes is thrown if an error occurs or no record # corresponds. # Because this method does not read the entity of a record, it is faster than `get'. # def vsiz(key) mod_vsiz(@index, key) end ## # bool = curia.iterinit() # Method: Initialize the iterator of the database handle. # The return value is always true. # An exception of `Curia::EANY' or its sub classes is thrown if an error occurs. # The iterator is used in order to access the key of every record stored in a database. # def iterinit() mod_iterinit(@index) end ## # str = curia.iternext() # Method: Get the next key of the iterator. # The return value is the value of the next key. If the silent flag is true and no record # corresponds, nil is returned instead of exception. # An exception of `Curia::EANY' or its sub classes is thrown if an error occurs or no record # is to be get out of the iterator. # It is possible to access every record by iteration of calling this method. However, it is # not assured if updating the database is occurred while the iteration. Besides, the order # of this traversal access method is arbitrary, so it is not assured that the order of # storing matches the one of the traversal access. # def iternext() mod_iternext(@index) end ## # bool = curia.setalign(align) # Method: Set alignment of the database handle. # `align' specifies the basic size of alignment. If it is omitted, alignment is cleared. # The return value is always true. # An exception of `Curia::EANY' or its sub classes is thrown if an error occurs. # If alignment is set to a database, the efficiency of overwriting values is improved. # The size of alignment is suggested to be average size of the values of the records to be # stored. If alignment is positive, padding whose size is multiple number of the alignment # is placed. If alignment is negative, as `vsiz' is the size of a value, the size of padding # is calculated with `(vsiz / pow(2, abs(align) - 1))'. Because alignment setting is not # saved in a database, you should specify alignment every opening a database. # def setalign(align = 0) mod_setalign(@index, align) end ## # bool = curia.setfbpsiz(size); # Method: Set the size of the free block pool. # `size' specifies the size of the free block pool. If it is undef, the free block pool is not # used. # The return value is always true. # An exception of `Curia::EANY' or its sub classes is thrown if an error occurs. # The default size of the free block pool is 16. If the size is greater, the space efficiency # of overwriting values is improved with the time efficiency sacrificed. # def setfbpsiz(size = 0) mod_setfbpsiz(@index, size) end ## # bool = curia.sync() # Method: Synchronize updating contents with the files and the devices. # The return value is always true. # An exception of `Curia::EANY' or its sub classes is thrown if an error occurs. # This method is useful when another process uses the connected database directory. # def sync() mod_sync(@index) end ## # bool = curia.optimize(bnum) # Method: Optimize the database. # `bnum' specifies the number of the elements of the bucket array. If it is omitted or not # more than 0, the default value is specified. # The return value is always true. # An exception of `Curia::EANY' or its sub classes is thrown if an error occurs. # In an alternating succession of deleting and storing with overwrite or concatenate, # dispensable regions accumulate. This method is useful to do away with them. # def optimize(bnum = -1) mod_optimize(@index, bnum) end ## # num = curia.fsiz() # Method: Get the total size of the database files. # The return value is the total size of the database files. # An exception of `Curia::EANY' or its sub classes is thrown if an error occurs. # If the total size is more than 2GB, the return value overflows. # def fsiz() mod_fsiz(@index) end ## # num = curia.bnum() # Method: Get the total number of the elements of each bucket array. # The return value is the total number of the elements of each bucket array # An exception of `Curia::EANY' or its sub classes is thrown if an error occurs. # def bnum() mod_bnum(@index) end ## # num = curia.rnum() # Method: Get the number of the records stored in the database. # The return value is the number of the records stored in the database. # An exception of `Curia::EANY' or its sub classes is thrown if an error occurs. # def rnum() mod_rnum(@index) end ## # num = curia.length() # Method: An alias of `rnum'. # alias length rnum ## # num = curia.size() # Method: An alias of `rnum'. # alias size rnum ## # bool = curia.writable() # Method: Check whether the database handle is a writer or not. # The return value is true if the handle is a writer, false if not. # An exception of `Curia::EANY' or its sub classes is thrown if an error occurs. # def writable() mod_writable(@index) end ## # bool = curia.fatalerror() # Method: Check whether the database has a fatal error or not. # The return value is true if the database has a fatal error, false if not. # An exception of `Curia::EANY' or its sub classes is thrown if an error occurs. # def fatalerror() mod_fatalerror(@index) end ## # curia.each() do |key, val| ... end # Iterator Method: Iterate a process with a pair of a key and a value of each record. # def each() MyMutex.synchronize() do iterinit() while(true) begin break unless key = iternext() val = get(key) rescue ENOITEM break end yield(key, val) end iterinit() end self end ## # curia.each_pair() do |key, val| ... end # Iterator Method: An alias of `each'. # alias each_pair each ## # curia.each_key() do |key| ... end # Iterator Method: Iterate a process with a key of each record. # def each_key() MyMutex.synchronize() do iterinit() while(true) begin break unless key = iternext() rescue ENOITEM break end yield(key) end iterinit() end self end ## # curia.each_value() do |val| ... end # Iterator Method: Iterate a process with a value of each record. # def each_value() MyMutex.synchronize() do iterinit() while(true) begin break unless key = iternext() val = get(key) rescue ENOITEM break end yield(val) end iterinit() end self end ## # ary = curia.keys() # Method: Get an array of all keys. # The return value is an array of all keys. # An exception of `Curia::EANY' or its sub classes is thrown if an error occurs. # def keys() ary = Array::new(rnum()) MyMutex.synchronize() do iterinit() 0.upto(ary.length - 1) do |i| ary[i] = iternext() end iterinit() end ary end ## # ary = curia.values() # Method: Get an array of all values. # The return value is an array of all values. # An exception of `Curia::EANY' or its sub classes is thrown if an error occurs. # def values() ary = Array::new(rnum()) MyMutex.synchronize() do iterinit() 0.upto(ary.length - 1) do |i| ary[i] = get(iternext()) end iterinit() end ary end ## # str = curia.index(val) # Method: Retrieve a record with a value. # `val' specifies a value. Although it must be an instance of String, binary data is okey. # The return value is the key of the record with the specified value. # An exception of `Curia::EANY' or its sub classes is thrown if an error occurs or no record # corresponds. # If two or more records correspond, the first found record is selected. # def index(val) key = nil MyMutex.synchronize() do iterinit() while(true) break unless key = iternext() (get(key) == val) && break end iterinit() end key end ## # num = curia.to_int() # Method: An alias of `rnum'. # alias to_int rnum ## # num = curia.to_i() # Method: An alias of `to_int'. # alias to_i to_int ## # str = curia.to_str() # Method: Get string standing for the instance. # def to_str if(@index != -1) sprintf("#", object_id(), @name, bnum(), rnum()) else sprintf("#", object_id(), @name) end end ## # str = curia.to_s() # Method: An alias of `to_str'. # alias to_s to_str ## # ary = curia.to_ary() # Method: Get an array of alternation of each pair of key and value. # def to_ary ary = Array::new(rnum()) i = 0 each() do |key, val| ary[i] = [key, val] i += 1 end ary end ## # ary = curia.to_a() # Method: An alias of `to_ary'. # alias to_a to_ary ## # hash = curia.to_hash() # Method: Get a hash storing all records. # def to_hash hash = Hash::new() each() do |key, val| hash[key] = val end hash end ## # hash = curia.to_h() # Method: An alias of `to_hash'. # alias to_h to_hash ## # str = curia.inspect() # Method: An alias of `to_str'. # alias inspect to_str end #---------------------------------------------------------------- # Alias definition of class methods #---------------------------------------------------------------- class << Curia alias open new end # END OF FILE qdbm-1.8.78/ruby/curia/mod_curia.c0000644000175000017500000003775710505745336015771 0ustar mikiomikio/************************************************************************************************* * Implementation of Curia for Ruby * Copyright (C) 2000-2006 Mikio Hirabayashi * This file is part of QDBM, Quick Database Manager. * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU * Lesser General Public License as published by the Free Software Foundation; either version * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * You should have received a copy of the GNU Lesser General Public License along with QDBM; if * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. *************************************************************************************************/ #include "ruby.h" #include #include #include #include #include #include #define MAXOPEN 1024 VALUE ccuriaerror; VALUE ccuriaerror_ENOERR; VALUE ccuriaerror_EFATAL; VALUE ccuriaerror_EMODE; VALUE ccuriaerror_EBROKEN; VALUE ccuriaerror_EKEEP; VALUE ccuriaerror_ENOITEM; VALUE ccuriaerror_EALLOC; VALUE ccuriaerror_EMAP; VALUE ccuriaerror_EOPEN; VALUE ccuriaerror_ECLOSE; VALUE ccuriaerror_ETRUNC; VALUE ccuriaerror_ESYNC; VALUE ccuriaerror_ESTAT; VALUE ccuriaerror_ESEEK; VALUE ccuriaerror_EREAD; VALUE ccuriaerror_EWRITE; VALUE ccuriaerror_ELOCK; VALUE ccuriaerror_EUNLINK; VALUE ccuriaerror_EMKDIR; VALUE ccuriaerror_ERMDIR; VALUE ccuriaerror_EMISC; VALUE mcuria; CURIA *crtable[MAXOPEN]; char crsltable[MAXOPEN]; static void crinit(void); static int getnewindex(void); static int checkdup(const char *name); static void myerror(int ecode); static VALUE rbcrversion(VALUE vself); static VALUE rbcrerrmsg(VALUE vself, VALUE vecode); static VALUE rbcropen(VALUE vself, VALUE vname, VALUE vomode, VALUE vbnum, VALUE vdnum); static VALUE rbcrclose(VALUE vself, VALUE vindex); static VALUE rbcrsetsilent(VALUE vself, VALUE vindex, VALUE vvalue); static VALUE rbcrput(VALUE vself, VALUE vindex, VALUE vkey, VALUE vval, VALUE vdmode); static VALUE rbcrout(VALUE vself, VALUE vindex, VALUE vkey); static VALUE rbcrget(VALUE vself, VALUE vindex, VALUE vkey, VALUE vstart, VALUE vmax); static VALUE rbcrvsiz(VALUE vself, VALUE vindex, VALUE vkey); static VALUE rbcriterinit(VALUE vself, VALUE vindex); static VALUE rbcriternext(VALUE vself, VALUE vindex); static VALUE rbcrsetalign(VALUE vself, VALUE vindex, VALUE valign); static VALUE rbcrsetfbpsiz(VALUE vself, VALUE vindex, VALUE vsize); static VALUE rbcrsync(VALUE vself, VALUE vindex); static VALUE rbcroptimize(VALUE vself, VALUE vindex, VALUE vbnum); static VALUE rbcrfsiz(VALUE vself, VALUE vindex); static VALUE rbcrbnum(VALUE vself, VALUE vindex); static VALUE rbcrrnum(VALUE vself, VALUE vindex); static VALUE rbcrwritable(VALUE vself, VALUE vindex); static VALUE rbcrfatalerror(VALUE vself, VALUE vindex); /************************************************************************************************* * public objects *************************************************************************************************/ Init_mod_curia(){ crinit(); ccuriaerror = rb_define_class("CuriaError", rb_eStandardError); ccuriaerror_ENOERR = rb_define_class("CuriaError_ENOERR", ccuriaerror); ccuriaerror_EFATAL = rb_define_class("CuriaError_EFATAL", ccuriaerror); ccuriaerror_EMODE = rb_define_class("CuriaError_EMODE", ccuriaerror); ccuriaerror_EBROKEN = rb_define_class("CuriaError_EBROKEN", ccuriaerror); ccuriaerror_EKEEP = rb_define_class("CuriaError_EKEEP", ccuriaerror); ccuriaerror_ENOITEM = rb_define_class("CuriaError_ENOITEM", ccuriaerror); ccuriaerror_EALLOC = rb_define_class("CuriaError_EALLOC", ccuriaerror); ccuriaerror_EMAP = rb_define_class("CuriaError_EMAP", ccuriaerror); ccuriaerror_EOPEN = rb_define_class("CuriaError_EOPEN", ccuriaerror); ccuriaerror_ECLOSE = rb_define_class("CuriaError_ECLOSE", ccuriaerror); ccuriaerror_ETRUNC = rb_define_class("CuriaError_ETRUNC", ccuriaerror); ccuriaerror_ESYNC = rb_define_class("CuriaError_ESYNC", ccuriaerror); ccuriaerror_ESTAT = rb_define_class("CuriaError_ESTAT", ccuriaerror); ccuriaerror_ESEEK = rb_define_class("CuriaError_ESEEK", ccuriaerror); ccuriaerror_EREAD = rb_define_class("CuriaError_EREAD", ccuriaerror); ccuriaerror_EWRITE = rb_define_class("CuriaError_EWRITE", ccuriaerror); ccuriaerror_ELOCK = rb_define_class("CuriaError_ELOCK", ccuriaerror); ccuriaerror_EUNLINK = rb_define_class("CuriaError_EUNLINK", ccuriaerror); ccuriaerror_EMKDIR = rb_define_class("CuriaError_EMKDIR", ccuriaerror); ccuriaerror_ERMDIR = rb_define_class("CuriaError_ERMDIR", ccuriaerror); ccuriaerror_EMISC = rb_define_class("CuriaError_EMISC", ccuriaerror); mcuria = rb_define_module("Mod_Curia"); rb_define_const(mcuria, "EANY", ccuriaerror); rb_define_const(mcuria, "ENOERR", ccuriaerror_ENOERR); rb_define_const(mcuria, "EFATAL", ccuriaerror_EFATAL); rb_define_const(mcuria, "EMODE", ccuriaerror_EMODE); rb_define_const(mcuria, "EBROKEN", ccuriaerror_EBROKEN); rb_define_const(mcuria, "EKEEP", ccuriaerror_EKEEP); rb_define_const(mcuria, "ENOITEM", ccuriaerror_ENOITEM); rb_define_const(mcuria, "EALLOC", ccuriaerror_EALLOC); rb_define_const(mcuria, "EMAP", ccuriaerror_EMAP); rb_define_const(mcuria, "EOPEN", ccuriaerror_EOPEN); rb_define_const(mcuria, "ECLOSE", ccuriaerror_ECLOSE); rb_define_const(mcuria, "ETRUNC", ccuriaerror_ETRUNC); rb_define_const(mcuria, "ESYNC", ccuriaerror_ESYNC); rb_define_const(mcuria, "ESTAT", ccuriaerror_ESTAT); rb_define_const(mcuria, "ESEEK", ccuriaerror_ESEEK); rb_define_const(mcuria, "EREAD", ccuriaerror_EREAD); rb_define_const(mcuria, "EWRITE", ccuriaerror_EWRITE); rb_define_const(mcuria, "ELOCK", ccuriaerror_ELOCK); rb_define_const(mcuria, "EUNLINK", ccuriaerror_EUNLINK); rb_define_const(mcuria, "EMKDIR", ccuriaerror_EMKDIR); rb_define_const(mcuria, "ERMDIR", ccuriaerror_ERMDIR); rb_define_const(mcuria, "EMISC", ccuriaerror_EMISC); rb_define_const(mcuria, "OREADER", INT2FIX(CR_OREADER)); rb_define_const(mcuria, "OWRITER", INT2FIX(CR_OWRITER)); rb_define_const(mcuria, "OCREAT", INT2FIX(CR_OCREAT)); rb_define_const(mcuria, "OTRUNC", INT2FIX(CR_OTRUNC)); rb_define_const(mcuria, "ONOLCK", INT2FIX(CR_ONOLCK)); rb_define_const(mcuria, "OLCKNB", INT2FIX(CR_OLCKNB)); rb_define_const(mcuria, "OSPARSE", INT2FIX(CR_OSPARSE)); rb_define_const(mcuria, "DOVER", INT2FIX(CR_DOVER)); rb_define_const(mcuria, "DKEEP", INT2FIX(CR_DKEEP)); rb_define_const(mcuria, "DCAT", INT2FIX(CR_DCAT)); rb_define_module_function(mcuria, "mod_open", rbcropen, 4); rb_define_module_function(mcuria, "mod_close", rbcrclose, 1); rb_define_module_function(mcuria, "mod_setsilent", rbcrsetsilent, 2); rb_define_module_function(mcuria, "mod_put", rbcrput, 4); rb_define_module_function(mcuria, "mod_out", rbcrout, 2); rb_define_module_function(mcuria, "mod_get", rbcrget, 4); rb_define_module_function(mcuria, "mod_vsiz", rbcrvsiz, 2); rb_define_module_function(mcuria, "mod_iterinit", rbcriterinit, 1); rb_define_module_function(mcuria, "mod_iternext", rbcriternext, 1); rb_define_module_function(mcuria, "mod_setalign", rbcrsetalign, 2); rb_define_module_function(mcuria, "mod_setfbpsiz", rbcrsetfbpsiz, 2); rb_define_module_function(mcuria, "mod_sync", rbcrsync, 1); rb_define_module_function(mcuria, "mod_optimize", rbcroptimize, 2); rb_define_module_function(mcuria, "mod_fsiz", rbcrfsiz, 1); rb_define_module_function(mcuria, "mod_bnum", rbcrbnum, 1); rb_define_module_function(mcuria, "mod_rnum", rbcrrnum, 1); rb_define_module_function(mcuria, "mod_writable", rbcrwritable, 1); rb_define_module_function(mcuria, "mod_fatalerror", rbcrfatalerror, 1); } /************************************************************************************************* * private objects *************************************************************************************************/ static void crinit(void){ int i; for(i = 0; i < MAXOPEN; i++){ crtable[i] = NULL; crsltable[i] = 0; } } static int getnewindex(void){ int i; for(i = 0; i < MAXOPEN; i++){ if(crtable[i] == NULL) return i; } return -1; } static int checkdup(const char *name){ struct stat sbuf; int i, inode; if(stat(name, &sbuf) == -1) return 0; inode = sbuf.st_ino; for(i = 0; i < MAXOPEN; i++){ if(crtable[i] != NULL && crinode(crtable[i]) == inode) return -1; } return 0; } static void myerror(int ecode){ VALUE verr; switch(ecode){ case DP_ENOERR: verr = ccuriaerror_ENOERR; break; case DP_EFATAL: verr = ccuriaerror_EFATAL; break; case DP_EMODE: verr = ccuriaerror_EMODE; break; case DP_EBROKEN: verr = ccuriaerror_EBROKEN; break; case DP_EKEEP: verr = ccuriaerror_EKEEP; break; case DP_ENOITEM: verr = ccuriaerror_ENOITEM; break; case DP_EALLOC: verr = ccuriaerror_EALLOC; break; case DP_EMAP: verr = ccuriaerror_EMAP; break; case DP_EOPEN: verr = ccuriaerror_EOPEN; break; case DP_ECLOSE: verr = ccuriaerror_ECLOSE; break; case DP_ETRUNC: verr = ccuriaerror_ETRUNC; break; case DP_ESYNC: verr = ccuriaerror_ESYNC; break; case DP_ESTAT: verr = ccuriaerror_ESTAT; break; case DP_ESEEK: verr = ccuriaerror_ESEEK; break; case DP_EREAD: verr = ccuriaerror_EREAD; break; case DP_EWRITE: verr = ccuriaerror_EWRITE; break; case DP_ELOCK: verr = ccuriaerror_ELOCK; break; case DP_EUNLINK: verr = ccuriaerror_EUNLINK; break; case DP_EMKDIR: verr = ccuriaerror_EMKDIR; break; case DP_ERMDIR: verr = ccuriaerror_ERMDIR; break; case DP_EMISC: verr = ccuriaerror_EMISC; break; default: verr = ccuriaerror; break; } rb_raise(verr, "%s", dperrmsg(ecode)); } static VALUE rbcropen(VALUE vself, VALUE vname, VALUE vomode, VALUE vbnum, VALUE vdnum){ CURIA *curia; const char *name; int index, omode, bnum, dnum; if((index = getnewindex()) == -1) myerror(DP_EMISC); name = STR2CSTR(vname); FIXNUM_P(vomode); omode = FIX2INT(vomode); FIXNUM_P(vbnum); bnum = FIX2INT(vbnum); FIXNUM_P(vdnum); dnum = FIX2INT(vdnum); if(checkdup(name) == -1) myerror(DP_EMISC); curia = cropen(name, omode, bnum, dnum); if(!curia) myerror(dpecode); crtable[index] = curia; crsltable[index] = 0; return INT2FIX(index); } static VALUE rbcrclose(VALUE vself, VALUE vindex){ CURIA *curia; int index; FIXNUM_P(vindex); if((index = FIX2INT(vindex)) == -1) myerror(DP_EMISC); curia = crtable[index]; crtable[index] = NULL; if(!crclose(curia)) myerror(dpecode); return Qtrue; } static VALUE rbcrsetsilent(VALUE vself, VALUE vindex, VALUE vvalue){ int index; FIXNUM_P(vindex); if((index = FIX2INT(vindex)) == -1) myerror(DP_EMISC); crsltable[index] = FIX2INT(vvalue); return Qnil; } static VALUE rbcrput(VALUE vself, VALUE vindex, VALUE vkey, VALUE vval, VALUE vdmode){ CURIA *curia; const char *kbuf, *vbuf; int index, ksiz, vsiz, dmode; FIXNUM_P(vindex); if((index = FIX2INT(vindex)) == -1) myerror(DP_EMISC); kbuf = STR2CSTR(vkey); ksiz = RSTRING(vkey)->len; vbuf = STR2CSTR(vval); vsiz = RSTRING(vval)->len; FIXNUM_P(vdmode); dmode = FIX2INT(vdmode); curia = crtable[index]; if(!crput(curia, kbuf, ksiz, vbuf, vsiz, dmode)){ if(crsltable[index] && dpecode == DP_EKEEP) return Qfalse; myerror(dpecode); } return Qtrue; } static VALUE rbcrout(VALUE vself, VALUE vindex, VALUE vkey){ CURIA *curia; const char *kbuf; int index, ksiz; FIXNUM_P(vindex); if((index = FIX2INT(vindex)) == -1) myerror(DP_EMISC); kbuf = STR2CSTR(vkey); ksiz = RSTRING(vkey)->len; curia = crtable[index]; if(!crout(curia, kbuf, ksiz)){ if(crsltable[index] && dpecode == DP_ENOITEM) return Qfalse; myerror(dpecode); } return Qtrue; } static VALUE rbcrget(VALUE vself, VALUE vindex, VALUE vkey, VALUE vstart, VALUE vmax){ CURIA *curia; const char *kbuf; char *vbuf; int index, ksiz, start, max, vsiz; VALUE vval; FIXNUM_P(vindex); if((index = FIX2INT(vindex)) == -1) myerror(DP_EMISC); kbuf = STR2CSTR(vkey); ksiz = RSTRING(vkey)->len; FIXNUM_P(vstart); start = FIX2INT(vstart); FIXNUM_P(vmax); max = FIX2INT(vmax); curia = crtable[index]; if(!(vbuf = crget(curia, kbuf, ksiz, start, max, &vsiz))){ if(crsltable[index] && dpecode == DP_ENOITEM) return Qnil; myerror(dpecode); } vval = rb_str_new(vbuf, vsiz); free(vbuf); return vval; } static VALUE rbcrvsiz(VALUE vself, VALUE vindex, VALUE vkey){ CURIA *curia; const char *kbuf; int index, ksiz, vsiz; FIXNUM_P(vindex); if((index = FIX2INT(vindex)) == -1) myerror(DP_EMISC); kbuf = STR2CSTR(vkey); ksiz = RSTRING(vkey)->len; curia = crtable[index]; if((vsiz = crvsiz(curia, kbuf, ksiz)) == -1){ if(crsltable[index] && dpecode == DP_ENOITEM) return INT2FIX(-1); myerror(dpecode); } return INT2FIX(vsiz); } static VALUE rbcriterinit(VALUE vself, VALUE vindex){ CURIA *curia; int index; FIXNUM_P(vindex); if((index = FIX2INT(vindex)) == -1) myerror(DP_EMISC); curia = crtable[index]; if(!criterinit(curia)) myerror(dpecode); return Qtrue; } static VALUE rbcriternext(VALUE vself, VALUE vindex){ CURIA *curia; char *kbuf; int index, ksiz; VALUE vkey; FIXNUM_P(vindex); if((index = FIX2INT(vindex)) == -1) myerror(DP_EMISC); curia = crtable[index]; if(!(kbuf = criternext(curia, &ksiz))){ if(crsltable[index] && dpecode == DP_ENOITEM) return Qnil; myerror(dpecode); } vkey = rb_str_new(kbuf, ksiz); free(kbuf); return vkey; } static VALUE rbcrsetalign(VALUE vself, VALUE vindex, VALUE valign){ CURIA *curia; int index, align; FIXNUM_P(vindex); if((index = FIX2INT(vindex)) == -1) myerror(DP_EMISC); FIXNUM_P(valign); align = FIX2INT(valign); curia = crtable[index]; if(!crsetalign(curia, align)) myerror(dpecode); return Qtrue; } static VALUE rbcrsetfbpsiz(VALUE vself, VALUE vindex, VALUE vsize){ CURIA *curia; int index, size; FIXNUM_P(vindex); if((index = FIX2INT(vindex)) == -1) myerror(DP_EMISC); FIXNUM_P(vsize); size = FIX2INT(vsize); curia = crtable[index]; if(!crsetfbpsiz(curia, size)) myerror(dpecode); return Qtrue; } static VALUE rbcrsync(VALUE vself, VALUE vindex){ CURIA *curia; int index; FIXNUM_P(vindex); if((index = FIX2INT(vindex)) == -1) myerror(DP_EMISC); curia = crtable[index]; if(!crsync(curia)) myerror(dpecode); return Qtrue; } static VALUE rbcroptimize(VALUE vself, VALUE vindex, VALUE vbnum){ CURIA *curia; int index, bnum; FIXNUM_P(vindex); if((index = FIX2INT(vindex)) == -1) myerror(DP_EMISC); FIXNUM_P(vbnum); bnum = FIX2INT(vbnum); curia = crtable[index]; if(!croptimize(curia, bnum)) myerror(dpecode); return Qtrue; } static VALUE rbcrfsiz(VALUE vself, VALUE vindex){ CURIA *curia; int index, fsiz; FIXNUM_P(vindex); if((index = FIX2INT(vindex)) == -1) myerror(DP_EMISC); curia = crtable[index]; if((fsiz = crfsiz(curia)) == -1) myerror(dpecode); return INT2FIX(fsiz); } static VALUE rbcrbnum(VALUE vself, VALUE vindex){ CURIA *curia; int index, bnum; FIXNUM_P(vindex); if((index = FIX2INT(vindex)) == -1) myerror(DP_EMISC); curia = crtable[index]; if((bnum = crbnum(curia)) == -1) myerror(dpecode); return INT2FIX(bnum); } static VALUE rbcrrnum(VALUE vself, VALUE vindex){ CURIA *curia; int index, rnum; FIXNUM_P(vindex); if((index = FIX2INT(vindex)) == -1) myerror(DP_EMISC); curia = crtable[index]; if((rnum = crrnum(curia)) == -1) myerror(dpecode); return INT2FIX(rnum); } static VALUE rbcrwritable(VALUE vself, VALUE vindex){ CURIA *curia; int index; FIXNUM_P(vindex); if((index = FIX2INT(vindex)) == -1) myerror(DP_EMISC); curia = crtable[index]; return crwritable(curia) ? Qtrue : Qfalse; } static VALUE rbcrfatalerror(VALUE vself, VALUE vindex){ CURIA *curia; int index; FIXNUM_P(vindex); if((index = FIX2INT(vindex)) == -1) myerror(DP_EMISC); curia = crtable[index]; return crfatalerror(curia) ? Qtrue : Qfalse; } /* END OF FILE */ qdbm-1.8.78/ruby/depot/0000755000175000017500000000000010705266455013652 5ustar mikiomikioqdbm-1.8.78/ruby/depot/MANIFEST0000644000175000017500000000006207727054636015007 0ustar mikiomikioMANIFEST extconf.rb depot.rb mod_depot.c rbdptest qdbm-1.8.78/ruby/depot/extconf.rb0000644000175000017500000000070310363125111015624 0ustar mikiomikiorequire 'mkmf' dir_config("depot") home = ENV['HOME'] $CFLAGS = "-I. -I../.. -I#{home}/include -I/usr/local/include" $LDFLAGS = "-L../.. -L#{home}/lib -L/usr/local/lib" $LIBS = "-L../.. -L#{home}/lib -L/usr/local/lib" have_library("c", "main") have_library("pthread", "main") have_library("z", "main") have_library("bz2", "main") have_library("lzo2", "main") have_library("iconv", "main") have_library("qdbm", "main") create_makefile("mod_depot") qdbm-1.8.78/ruby/depot/rbdptest0000755000175000017500000001471310505767066015437 0ustar mikiomikio#! /usr/bin/ruby -w #================================================================================================= # Test cases of Depot for Ruby # Copyright (C) 2000-2005 Mikio Hirabayashi # This file is part of QDBM, Quick Database Manager. # QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU # Lesser General Public License as published by the Free Software Foundation; either version # 2.1 of the License or any later version. QDBM is distributed in the hope that it will be # useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more # details. # You should have received a copy of the GNU Lesser General Public License along with QDBM; if # not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA # 02111-1307 USA. #================================================================================================= require 'depot' # main routine def main() $0.gsub!(/.*\//, "") (ARGV.length >= 1) || usage() if(ARGV[0] == "write") rv = runwrite() elsif(ARGV[0] == "read") rv = runread() elsif(ARGV[0] == "misc") rv = runmisc() else usage() end return rv end # print the usage and exit def usage() printf(STDERR, "%s: test cases for Depot for Ruby\n", $0) printf(STDERR, "\n") printf(STDERR, "usage:\n") printf(STDERR, " %s write name rnum bnum\n", $0) printf(STDERR, " %s read name\n", $0) printf(STDERR, " %s misc name\n", $0) printf(STDERR, "\n") exit(1) end # parse arguments of write command def runwrite() name = nil rnum = -1 bnum = -1 i = 1 while(i < ARGV.length) if(!name && ARGV[i] =~ /^-/) usage() elsif(!name) name = ARGV[i] elsif(rnum < 0) rnum = ARGV[i].to_i() elsif(bnum < 0) bnum = ARGV[i].to_i() else usage() end i += 1 end (name && rnum > 0 && bnum > 0) || usage() dowrite(name, rnum, bnum) return 0 end # parse arguments of read command def runread() name = nil i = 1 while(i < ARGV.length) if(!name && ARGV[i] =~ /^-/) usage() elsif(!name) name = ARGV[i] else usage() end i += 1 end (name) || usage() doread(name) return 0 end # parse arguments of misc command def runmisc() name = nil i = 1 while(i < ARGV.length) if(!name && ARGV[i] =~ /^-/) usage() elsif(!name) name = ARGV[i] else usage() end i += 1 end (name) || usage() domisc(name) return 0 end # perform write command def dowrite(name, rnum, bnum) printf("\n name=%s rnum=%d bnum=%d\n\n", name, rnum, bnum) depot = nil begin # open a database depot = Depot::new(name, Depot::OWRITER | Depot::OCREAT | Depot::OTRUNC, bnum) # loop for each record STDOUT.sync = true 1.upto(rnum) do |i| buf = sprintf("%08d", i) # store a record depot.put(buf, buf) # print progression if(rnum > 250 && i % (rnum / 250) == 0) print(".") if(i == rnum || i % (rnum / 10) == 0) printf(" (%08d)\n", i) end end end rescue printf("%s: %s: %s\n", $0, name, $!) return 1 ensure begin # close the database (depot) && depot.close() rescue return 1 end end printf("ok\n\n") return 0 end # perform read command def doread(name) printf("\n name=%s\n\n", name) depot = nil begin # open a database depot = Depot::new(name) # get the number of record rnum = depot.rnum() # loop for each record STDOUT.sync = true 1.upto(rnum) do |i| buf = sprintf("%08d", i) # store a record depot.get(buf) # print progression if(rnum > 250 && i % (rnum / 250) == 0) print(".") if(i == rnum || i % (rnum / 10) == 0) printf(" (%08d)\n", i) end end end rescue printf("%s: %s: %s\n", $0, name, $!) return 1 ensure begin # close the database (depot) && depot.close() rescue return 1 end end printf("ok\n\n") return 0 end # perform misc command def domisc(name) loopnum = 500 bucketnum = 16 threadnum = 10 printf("\n name=%s\n\n", name) depot = nil begin # open the database printf("Creating a database ... ") depot = Depot::open("casket", Depot::OWRITER | Depot::OCREAT | Depot::OTRUNC, bucketnum) printf("ok\n") # store records printf("Storing records ... ") 1.upto(loopnum) do |i| buf = sprintf("%08d", i) depot[buf] = buf end printf("ok\n") # retrieve records printf("Retrieving records ... ") 1.upto(loopnum) do |i| buf = sprintf("%08d", i) (depot[buf] == buf) || raise("key and value does not match") end printf("ok\n") # traverse records printf("Traversing records ... ") depot.each() do |key, val| (key == val) || raise("key and value does not match") end depot.keys() depot.values() printf("ok\n") # silent mode operations printf("Silent mode operations ... ") depot.silent = true depot.put("foo", "bar", Depot::DKEEP) depot.put("foo", "bar", Depot::DKEEP) depot.get("foo") depot.out("foo") depot.out("foo") depot.get("nil") depot.fetch("nil", "void"); depot.keys() depot.values() printf("ok\n") rescue printf("%s: %s: %s\n", $0, name, $!) return 1 ensure # close the database printf("Closing the database ... ") (depot) && depot.close() printf("ok\n") end # test iterator and threads printf("Processing with iterator and threads ... ") Depot::new("casket", Depot::OWRITER) do |depot| (depot.rnum() == loopnum) || raise("record number is invalid") depot.clear() threads = [] 1.upto(threadnum) do |i| t = Thread::new() do 1.upto(loopnum) do |j| buf = sprintf("%08d", j) depot.put(buf, "*", Depot::DCAT) end end threads.push(t) end threads.each do |t| t.join() end 1.upto(loopnum) do |i| buf = sprintf("%08d", i) (depot.vsiz(buf) == threadnum) || raise("thread writing is invalid") end (depot.index("*" * threadnum)) || raise("thread writing is invalid") end printf("ok\n") printf("all ok\n\n") return 0 end # execute main $0.gsub!(/.*\//, "") exit(main()) # END OF FILE qdbm-1.8.78/ruby/depot/lib/0000755000175000017500000000000010505770173014413 5ustar mikiomikioqdbm-1.8.78/ruby/depot/lib/depot.rb0000644000175000017500000004631010505767264016066 0ustar mikiomikio#================================================================================================= # Ruby API of Depot, the basic API of QDBM # Copyright (C) 2000-2006 Mikio Hirabayashi # This file is part of QDBM, Quick Database Manager. # QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU # Lesser General Public License as published by the Free Software Foundation; either version # 2.1 of the License or any later version. QDBM is distributed in the hope that it will be # useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more # details. # You should have received a copy of the GNU Lesser General Public License along with QDBM; if # not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA # 02111-1307 USA. #================================================================================================= require 'mod_depot' require 'thread' ## # require 'depot' # The library `depot' should be included in application codes. # An instance of the class `Depot' is used as a database handle. # `Depot' performs Mix-in of `Enumerable'. # Each method of `Depot' throws an exception of `Depot::EANY' or its sub classes when an error # occurs: `Depot::ENOERR', `Depot::EFATAL', `Depot::EMODE', `Depot::EBROKEN', `Depot::EKEEP', # `Depot::ENOITEM', `Depot::EALLOC', `Depot::EMAP', `Depot::EOPEN', `Depot::ECLOSE', # `Depot::ETRUNC', `Depot::ESYNC', `Depot::ESTAT', `Depot::ESEEK', `Depot::EREAD', # `Depot::EWRITE', `Depot::ELOCK', `Depot::EUNLINK', `Depot::EMKDIR', `Depot::ERMDIR' and # `Depot::EMISC'. # class Depot include Mod_Depot, Enumerable #---------------------------------------------------------------- # class constants #---------------------------------------------------------------- MyMutex = Mutex::new() #---------------------------------------------------------------- # class methods #---------------------------------------------------------------- public ## # depot = Depot::new(name, omode, bnum) # Constructor: Get a database handle. # `name' specifies the name of a database file. # `omode' specifies the connection mode: `Depot::OWRITER' as a writer, `Depot::OREADER' as a # reader. If the mode is `Depot::OWRITER', the following may be added by bitwise or: # `Depot::OCREAT', which means it creates a new database if not exist, `Depot::OTRUNC', which # means it creates a new database regardless if one exists. Both of `Depot::OREADER' and # `Depot::OWRITER' can be added to by bitwise or: `Depot::ONOLCK', which means it opens a # database file without file locking, or `Depot::OLCKNB', which means locking is performed # without blocking. `Depot::OCREAT' can be added to by bitwise or: `Depot::OSPARSE', which # means it creates a database file as a sparse file. If it is omitted, `Depot::OREADER' is # specified. # `bnum' specifies the number of elements of the bucket array. If it is omitted or not more # than 0, the default value is specified. The size of a bucket array is determined on # creating, and can not be changed except for by optimization of the database. Suggested # size of a bucket array is about from 0.5 to 4 times of the number of all records to store. # The return value is the database handle. # An exception of `Depot::EANY' or its sub classes is thrown if an error occurs. # If a block parameter is given, this method works as an iterator. A database handle is # opened and passed via the first argument of the block. The database handle is surely # closed when the block is over. # While connecting as a writer, an exclusive lock is invoked to the database file. # While connecting as a reader, a shared lock is invoked to the database file. The thread # blocks until the lock is achieved. If `Depot::ONOLCK' is used, the application is # responsible for exclusion control. # #@ DEFINED IMPLICITLY ## # depot = Depot::open(name, omode, bnum) # Constructor: An alias of `new'. # #@ DEFINED OUTSIDE #---------------------------------------------------------------- # private methods #---------------------------------------------------------------- private #= # initialize(name, omode, bnum) # Method: Called implicitly by the constructor. # def initialize(name, omode = OREADER, bnum = -1) @silent = false MyMutex.synchronize() do @index = mod_open(name, omode, bnum) @name = name end if(iterator?) begin yield(self) ensure close() end end self end #= # clone() # Method: Forbidden to use. # def clone raise(DepotError) end #= # dup() # Method: Forbidden to use. # alias dup clone #---------------------------------------------------------------- # public methods #---------------------------------------------------------------- public ## # bool = depot.close() # Method: Close the database handle. # The return value is always true. # An exception of `Depot::EANY' or its sub classes is thrown if an error occurs. # Because the region of a closed handle is released, it becomes impossible to use the handle. # Updating a database is assured to be written when the handle is closed. If a writer opens # a database but does not close it appropriately, the database will be broken. # def close() MyMutex.synchronize() do begin mod_close(@index) ensure @index = -1 end end end ## # depot.silent = bool # Method: Set the flag whether to repress frequent exceptions. # The return value is the assigned value. # def silent=(value) @silent = value ? true : false mod_setsilent(@index, silent ? 1 : 0) @silent end def silent @silent end ## # bool = depot.put(key, val, dmode) # Method: Store a record. # `key' specifies a key. Although it must be an instance of String, binary data is okey. # `val' specifies a value. Although it must be an instance of String, binary data is okey. # `dmode' specifies behavior when the key overlaps, by the following values: `Depot::DOVER', # which means the specified value overwrites the existing one, `Depot::DKEEP', which means # the existing value is kept, `Depot::DCAT', which means the specified value is concatenated # at the end of the existing value. If it is omitted, `Depot::DOVER' is specified. # The return value is always true. However, if the silent flag is true and replace is # cancelled, false is returned instead of exception. # An exception of `Depot::EANY' or its sub classes is thrown if an error occurs or replace # is cancelled. # def put(key, val, dmode = DOVER) mod_put(@index, key, val, dmode) end ## # bool = depot.store(key, val) # Method: An alias of `put'. # alias store put ## # depot[key] = val # Method: An alias of `put'. # alias []= put ## # bool = depot.out(key) # Method: Delete a record. # `key' specifies a key. Although it must be an instance of String, binary data is okey. # The return value is always true. However, if the silent flag is true and no record # corresponds, false is returned instead of exception. # An exception of `Depot::EANY' or its sub classes is thrown if an error occurs or no record # corresponds. # def out(key) mod_out(@index, key) end ## # bool = depot.delete(key) # Method: An alias of `out'. # alias delete out ## # bool = depot.clear() # Method: Delete all records. # The return value is always true. # An exception of `Depot::EANY' or its sub classes is thrown if an error occurs. # def clear MyMutex.synchronize() do iterinit() while(rnum() > 0) out(iternext()) end end true end ## # str = depot.get(key, start, max) # Method: Retrieve a record. # `key' specifies a key. Although it must be an instance of String, binary data is okey. # `start' specifies the offset address of the beginning of the region of the value to be read. # If it is negative or omitted, the offset is specified as 0. # `max' specifies the max size to be read. If it is negative or omitted, the size to read is # unlimited. # The return value is an instance of the value of the corresponding record. If the silent flag # is true and no record corresponds, nil is returned instead of exception. # An exception of `Depot::EANY' or its sub classes is thrown if an error occurs, no record # corresponds, or the size of the value of the corresponding record is less than `max'. # def get(key, start = 0, max = -1) mod_get(@index, key, start, max) end ## # str = depot.fetch(key, defval) # Method: Retrieve a record. # `key' specifies a key. Although it must be an instance of String, binary data is okey. # `defval' specifies the default value used when no record corresponds. If it is omitted, nil # is specified. # The return value is an instance of the value of the corresponding record, or the default # value if no record corresponds. # An exception of `Depot::EANY' or its sub classes is thrown if an error occurs. # def fetch(key, defval = nil) if @silent if val = mod_get(@index, key, 0, -1) val else defval end else begin mod_get(@index, key, 0, -1) rescue ENOITEM defval end end end ## # str = depot[key] # Method: An alias of `fetch'. # alias [] fetch ## # num = depot.vsiz(key) # Method: Get the size of the value of a record. # `key' specifies a key. Although it must be an instance of String, binary data is okey. # The return value is the size of the value of the corresponding record. If the silent flag # is true and no record corresponds, -1 is returned instead of exception. # An exception of `Depot::EANY' or its sub classes is thrown if an error occurs or no record # corresponds. # Because this method does not read the entity of a record, it is faster than `get'. # def vsiz(key) mod_vsiz(@index, key) end ## # bool = depot.iterinit() # Method: Initialize the iterator of the database handle. # The return value is always true. # An exception of `Depot::EANY' or its sub classes is thrown if an error occurs. # The iterator is used in order to access the key of every record stored in a database. # def iterinit() mod_iterinit(@index) end ## # str = depot.iternext() # Method: Get the next key of the iterator. # The return value is the value of the next key. If the silent flag is true and no record # corresponds, nil is returned instead of exception. # An exception of `Depot::EANY' or its sub classes is thrown if an error occurs or no record # is to be get out of the iterator. # It is possible to access every record by iteration of calling this method. However, it is # not assured if updating the database is occurred while the iteration. Besides, the order # of this traversal access method is arbitrary, so it is not assured that the order of # storing matches the one of the traversal access. # def iternext() mod_iternext(@index) end ## # bool = depot.setalign(align) # Method: Set alignment of the database handle. # `align' specifies the basic size of alignment. If it is omitted, alignment is cleared. # The return value is always true. # An exception of `Depot::EANY' or its sub classes is thrown if an error occurs. # If alignment is set to a database, the efficiency of overwriting values is improved. # The size of alignment is suggested to be average size of the values of the records to be # stored. If alignment is positive, padding whose size is multiple number of the alignment # is placed. If alignment is negative, as `vsiz' is the size of a value, the size of padding # is calculated with `(vsiz / pow(2, abs(align) - 1))'. Because alignment setting is not # saved in a database, you should specify alignment every opening a database. # def setalign(align = 0) mod_setalign(@index, align) end ## # bool = depot.setfbpsiz(size); # Method: Set the size of the free block pool. # `size' specifies the size of the free block pool. If it is undef, the free block pool is not # used. # The return value is always true. # An exception of `Depot::EANY' or its sub classes is thrown if an error occurs. # The default size of the free block pool is 16. If the size is greater, the space efficiency # of overwriting values is improved with the time efficiency sacrificed. # def setfbpsiz(size = 0) mod_setfbpsiz(@index, size) end ## # bool = depot.sync() # Method: Synchronize updating contents with the file and the device. # The return value is always true. # An exception of `Depot::EANY' or its sub classes is thrown if an error occurs. # This method is useful when another process uses the connected database file. # def sync() mod_sync(@index) end ## # bool = depot.optimize(bnum) # Method: Optimize the database. # `bnum' specifies the number of the elements of the bucket array. If it is omitted or not # more than 0, the default value is specified. # The return value is always true. # An exception of `Depot::EANY' or its sub classes is thrown if an error occurs. # In an alternating succession of deleting and storing with overwrite or concatenate, # dispensable regions accumulate. This method is useful to do away with them. # def optimize(bnum = -1) mod_optimize(@index, bnum) end ## # num = depot.fsiz() # Method: Get the size of the database file. # The return value is the size of the database file. # An exception of `Depot::EANY' or its sub classes is thrown if an error occurs. # def fsiz() mod_fsiz(@index) end ## # num = depot.bnum() # Method: Get the number of the elements of the bucket array. # The return value is the number of the elements of the bucket array # An exception of `Depot::EANY' or its sub classes is thrown if an error occurs. # def bnum() mod_bnum(@index) end ## # num = depot.rnum() # Method: Get the number of the records stored in the database. # The return value is the number of the records stored in the database. # An exception of `Depot::EANY' or its sub classes is thrown if an error occurs. # def rnum() mod_rnum(@index) end ## # num = depot.length() # Method: An alias of `rnum'. # alias length rnum ## # num = depot.size() # Method: An alias of `rnum'. # alias size rnum ## # bool = depot.writable() # Method: Check whether the database handle is a writer or not. # The return value is true if the handle is a writer, false if not. # An exception of `Depot::EANY' or its sub classes is thrown if an error occurs. # def writable() mod_writable(@index) end ## # bool = depot.fatalerror() # Method: Check whether the database has a fatal error or not. # The return value is true if the database has a fatal error, false if not. # An exception of `Depot::EANY' or its sub classes is thrown if an error occurs. # def fatalerror() mod_fatalerror(@index) end ## # depot.each() do |key, val| ... end # Iterator Method: Iterate a process with a pair of a key and a value of each record. # def each() MyMutex.synchronize() do iterinit() while(true) begin break unless key = iternext() val = get(key) rescue ENOITEM break end yield(key, val) end iterinit() end self end ## # depot.each_pair() do |key, val| ... end # Iterator Method: An alias of `each'. # alias each_pair each ## # depot.each_key() do |key| ... end # Iterator Method: Iterate a process with a key of each record. # def each_key() MyMutex.synchronize() do iterinit() while(true) begin break unless key = iternext() rescue ENOITEM break end yield(key) end iterinit() end self end ## # depot.each_value() do |val| ... end # Iterator Method: Iterate a process with a value of each record. # def each_value() MyMutex.synchronize() do iterinit() while(true) begin break unless key = iternext() val = get(key) rescue ENOITEM break end yield(val) end iterinit() end self end ## # ary = depot.keys() # Method: Get an array of all keys. # The return value is an array of all keys. # An exception of `Depot::EANY' or its sub classes is thrown if an error occurs. # def keys() ary = Array::new(rnum()) MyMutex.synchronize() do iterinit() 0.upto(ary.length - 1) do |i| ary[i] = iternext() end iterinit() end ary end ## # ary = depot.values() # Method: Get an array of all values. # The return value is an array of all values. # An exception of `Depot::EANY' or its sub classes is thrown if an error occurs. # def values() ary = Array::new(rnum()) MyMutex.synchronize() do iterinit() 0.upto(ary.length - 1) do |i| ary[i] = get(iternext()) end iterinit() end ary end ## # str = depot.index(val) # Method: Retrieve a record with a value. # `val' specifies a value. Although it must be an instance of String, binary data is okey. # The return value is the key of the record with the specified value. # An exception of `Depot::EANY' or its sub classes is thrown if an error occurs or no record # corresponds. # If two or more records correspond, the first found record is selected. # def index(val) key = nil MyMutex.synchronize() do iterinit() while(true) break unless key = iternext() (get(key) == val) && break end iterinit() end key end ## # num = depot.to_int() # Method: An alias of `rnum'. # alias to_int rnum ## # num = depot.to_i() # Method: An alias of `to_int'. # alias to_i to_int ## # str = depot.to_str() # Method: Get string standing for the instance. # def to_str if(@index != -1) sprintf("#", object_id(), @name, bnum(), rnum()) else sprintf("#", object_id(), @name) end end ## # str = depot.to_s() # Method: An alias of `to_str'. # alias to_s to_str ## # ary = depot.to_ary() # Method: Get an array of alternation of each pair of a key and a value. # def to_ary ary = Array::new(rnum()) i = 0 each() do |key, val| ary[i] = [key, val] i += 1 end ary end ## # ary = depot.to_a() # Method: An alias of `to_ary'. # alias to_a to_ary ## # hash = depot.to_hash() # Method: Get a hash storing all records. # def to_hash hash = Hash::new() each() do |key, val| hash[key] = val end hash end ## # hash = depot.to_h() # Method: An alias of `to_hash'. # alias to_h to_hash ## # str = depot.inspect() # Method: An alias of `to_str'. # alias inspect to_str end #---------------------------------------------------------------- # Alias definition of class methods #---------------------------------------------------------------- class << Depot alias open new end # END OF FILE qdbm-1.8.78/ruby/depot/mod_depot.c0000644000175000017500000003761210505744722015775 0ustar mikiomikio/************************************************************************************************* * Implementation of Depot for Ruby * Copyright (C) 2000-2006 Mikio Hirabayashi * This file is part of QDBM, Quick Database Manager. * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU * Lesser General Public License as published by the Free Software Foundation; either version * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * You should have received a copy of the GNU Lesser General Public License along with QDBM; if * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. *************************************************************************************************/ #include "ruby.h" #include #include #include #include #include #define MAXOPEN 1024 VALUE cdepoterror; VALUE cdepoterror_ENOERR; VALUE cdepoterror_EFATAL; VALUE cdepoterror_EMODE; VALUE cdepoterror_EBROKEN; VALUE cdepoterror_EKEEP; VALUE cdepoterror_ENOITEM; VALUE cdepoterror_EALLOC; VALUE cdepoterror_EMAP; VALUE cdepoterror_EOPEN; VALUE cdepoterror_ECLOSE; VALUE cdepoterror_ETRUNC; VALUE cdepoterror_ESYNC; VALUE cdepoterror_ESTAT; VALUE cdepoterror_ESEEK; VALUE cdepoterror_EREAD; VALUE cdepoterror_EWRITE; VALUE cdepoterror_ELOCK; VALUE cdepoterror_EUNLINK; VALUE cdepoterror_EMKDIR; VALUE cdepoterror_ERMDIR; VALUE cdepoterror_EMISC; VALUE mdepot; DEPOT *dptable[MAXOPEN]; char dpsltable[MAXOPEN]; static void dpinit(void); static int getnewindex(void); static int checkdup(const char *name); static void myerror(int ecode); static VALUE rbdpversion(VALUE vself); static VALUE rbdperrmsg(VALUE vself, VALUE vecode); static VALUE rbdpopen(VALUE vself, VALUE vname, VALUE vomode, VALUE vbnum); static VALUE rbdpclose(VALUE vself, VALUE vindex); static VALUE rbdpsetsilent(VALUE vself, VALUE vindex, VALUE vvalue); static VALUE rbdpput(VALUE vself, VALUE vindex, VALUE vkey, VALUE vval, VALUE vdmode); static VALUE rbdpout(VALUE vself, VALUE vindex, VALUE vkey); static VALUE rbdpget(VALUE vself, VALUE vindex, VALUE vkey, VALUE vstart, VALUE vmax); static VALUE rbdpvsiz(VALUE vself, VALUE vindex, VALUE vkey); static VALUE rbdpiterinit(VALUE vself, VALUE vindex); static VALUE rbdpiternext(VALUE vself, VALUE vindex); static VALUE rbdpsetalign(VALUE vself, VALUE vindex, VALUE valign); static VALUE rbdpsetfbpsiz(VALUE vself, VALUE vindex, VALUE vsize); static VALUE rbdpsync(VALUE vself, VALUE vindex); static VALUE rbdpoptimize(VALUE vself, VALUE vindex, VALUE vbnum); static VALUE rbdpfsiz(VALUE vself, VALUE vindex); static VALUE rbdpbnum(VALUE vself, VALUE vindex); static VALUE rbdprnum(VALUE vself, VALUE vindex); static VALUE rbdpwritable(VALUE vself, VALUE vindex); static VALUE rbdpfatalerror(VALUE vself, VALUE vindex); /************************************************************************************************* * public objects *************************************************************************************************/ Init_mod_depot(){ dpinit(); cdepoterror = rb_define_class("DepotError", rb_eStandardError); cdepoterror_ENOERR = rb_define_class("DepotError_ENOERR", cdepoterror); cdepoterror_EFATAL = rb_define_class("DepotError_EFATAL", cdepoterror); cdepoterror_EMODE = rb_define_class("DepotError_EMODE", cdepoterror); cdepoterror_EBROKEN = rb_define_class("DepotError_EBROKEN", cdepoterror); cdepoterror_EKEEP = rb_define_class("DepotError_EKEEP", cdepoterror); cdepoterror_ENOITEM = rb_define_class("DepotError_ENOITEM", cdepoterror); cdepoterror_EALLOC = rb_define_class("DepotError_EALLOC", cdepoterror); cdepoterror_EMAP = rb_define_class("DepotError_EMAP", cdepoterror); cdepoterror_EOPEN = rb_define_class("DepotError_EOPEN", cdepoterror); cdepoterror_ECLOSE = rb_define_class("DepotError_ECLOSE", cdepoterror); cdepoterror_ETRUNC = rb_define_class("DepotError_ETRUNC", cdepoterror); cdepoterror_ESYNC = rb_define_class("DepotError_ESYNC", cdepoterror); cdepoterror_ESTAT = rb_define_class("DepotError_ESTAT", cdepoterror); cdepoterror_ESEEK = rb_define_class("DepotError_ESEEK", cdepoterror); cdepoterror_EREAD = rb_define_class("DepotError_EREAD", cdepoterror); cdepoterror_EWRITE = rb_define_class("DepotError_EWRITE", cdepoterror); cdepoterror_ELOCK = rb_define_class("DepotError_ELOCK", cdepoterror); cdepoterror_EUNLINK = rb_define_class("DepotError_EUNLINK", cdepoterror); cdepoterror_EMKDIR = rb_define_class("DepotError_EMKDIR", cdepoterror); cdepoterror_ERMDIR = rb_define_class("DepotError_ERMDIR", cdepoterror); cdepoterror_EMISC = rb_define_class("DepotError_EMISC", cdepoterror); mdepot = rb_define_module("Mod_Depot"); rb_define_const(mdepot, "EANY", cdepoterror); rb_define_const(mdepot, "ENOERR", cdepoterror_ENOERR); rb_define_const(mdepot, "EFATAL", cdepoterror_EFATAL); rb_define_const(mdepot, "EMODE", cdepoterror_EMODE); rb_define_const(mdepot, "EBROKEN", cdepoterror_EBROKEN); rb_define_const(mdepot, "EKEEP", cdepoterror_EKEEP); rb_define_const(mdepot, "ENOITEM", cdepoterror_ENOITEM); rb_define_const(mdepot, "EALLOC", cdepoterror_EALLOC); rb_define_const(mdepot, "EMAP", cdepoterror_EMAP); rb_define_const(mdepot, "EOPEN", cdepoterror_EOPEN); rb_define_const(mdepot, "ECLOSE", cdepoterror_ECLOSE); rb_define_const(mdepot, "ETRUNC", cdepoterror_ETRUNC); rb_define_const(mdepot, "ESYNC", cdepoterror_ESYNC); rb_define_const(mdepot, "ESTAT", cdepoterror_ESTAT); rb_define_const(mdepot, "ESEEK", cdepoterror_ESEEK); rb_define_const(mdepot, "EREAD", cdepoterror_EREAD); rb_define_const(mdepot, "EWRITE", cdepoterror_EWRITE); rb_define_const(mdepot, "ELOCK", cdepoterror_ELOCK); rb_define_const(mdepot, "EUNLINK", cdepoterror_EUNLINK); rb_define_const(mdepot, "EMKDIR", cdepoterror_EMKDIR); rb_define_const(mdepot, "ERMDIR", cdepoterror_ERMDIR); rb_define_const(mdepot, "EMISC", cdepoterror_EMISC); rb_define_const(mdepot, "OREADER", INT2FIX(DP_OREADER)); rb_define_const(mdepot, "OWRITER", INT2FIX(DP_OWRITER)); rb_define_const(mdepot, "OCREAT", INT2FIX(DP_OCREAT)); rb_define_const(mdepot, "OTRUNC", INT2FIX(DP_OTRUNC)); rb_define_const(mdepot, "ONOLCK", INT2FIX(DP_ONOLCK)); rb_define_const(mdepot, "OLCKNB", INT2FIX(DP_OLCKNB)); rb_define_const(mdepot, "OSPARSE", INT2FIX(DP_OSPARSE)); rb_define_const(mdepot, "DOVER", INT2FIX(DP_DOVER)); rb_define_const(mdepot, "DKEEP", INT2FIX(DP_DKEEP)); rb_define_const(mdepot, "DCAT", INT2FIX(DP_DCAT)); rb_define_module_function(mdepot, "mod_open", rbdpopen, 3); rb_define_module_function(mdepot, "mod_close", rbdpclose, 1); rb_define_module_function(mdepot, "mod_setsilent", rbdpsetsilent, 2); rb_define_module_function(mdepot, "mod_put", rbdpput, 4); rb_define_module_function(mdepot, "mod_out", rbdpout, 2); rb_define_module_function(mdepot, "mod_get", rbdpget, 4); rb_define_module_function(mdepot, "mod_vsiz", rbdpvsiz, 2); rb_define_module_function(mdepot, "mod_iterinit", rbdpiterinit, 1); rb_define_module_function(mdepot, "mod_iternext", rbdpiternext, 1); rb_define_module_function(mdepot, "mod_setalign", rbdpsetalign, 2); rb_define_module_function(mdepot, "mod_setfbpsiz", rbdpsetfbpsiz, 2); rb_define_module_function(mdepot, "mod_sync", rbdpsync, 1); rb_define_module_function(mdepot, "mod_optimize", rbdpoptimize, 2); rb_define_module_function(mdepot, "mod_fsiz", rbdpfsiz, 1); rb_define_module_function(mdepot, "mod_bnum", rbdpbnum, 1); rb_define_module_function(mdepot, "mod_rnum", rbdprnum, 1); rb_define_module_function(mdepot, "mod_writable", rbdpwritable, 1); rb_define_module_function(mdepot, "mod_fatalerror", rbdpfatalerror, 1); } /************************************************************************************************* * private objects *************************************************************************************************/ static void dpinit(void){ int i; for(i = 0; i < MAXOPEN; i++){ dptable[i] = NULL; dpsltable[i] = 0; } } static int getnewindex(void){ int i; for(i = 0; i < MAXOPEN; i++){ if(dptable[i] == NULL) return i; } return -1; } static int checkdup(const char *name){ struct stat sbuf; int i, inode; if(stat(name, &sbuf) == -1) return 0; inode = sbuf.st_ino; for(i = 0; i < MAXOPEN; i++){ if(dptable[i] != NULL && dpinode(dptable[i]) == inode) return -1; } return 0; } static void myerror(int ecode){ VALUE verr; switch(ecode){ case DP_ENOERR: verr = cdepoterror_ENOERR; break; case DP_EFATAL: verr = cdepoterror_EFATAL; break; case DP_EMODE: verr = cdepoterror_EMODE; break; case DP_EBROKEN: verr = cdepoterror_EBROKEN; break; case DP_EKEEP: verr = cdepoterror_EKEEP; break; case DP_ENOITEM: verr = cdepoterror_ENOITEM; break; case DP_EALLOC: verr = cdepoterror_EALLOC; break; case DP_EMAP: verr = cdepoterror_EMAP; break; case DP_EOPEN: verr = cdepoterror_EOPEN; break; case DP_ECLOSE: verr = cdepoterror_ECLOSE; break; case DP_ETRUNC: verr = cdepoterror_ETRUNC; break; case DP_ESYNC: verr = cdepoterror_ESYNC; break; case DP_ESTAT: verr = cdepoterror_ESTAT; break; case DP_ESEEK: verr = cdepoterror_ESEEK; break; case DP_EREAD: verr = cdepoterror_EREAD; break; case DP_EWRITE: verr = cdepoterror_EWRITE; break; case DP_ELOCK: verr = cdepoterror_ELOCK; break; case DP_EUNLINK: verr = cdepoterror_EUNLINK; break; case DP_EMKDIR: verr = cdepoterror_EMKDIR; break; case DP_ERMDIR: verr = cdepoterror_ERMDIR; break; case DP_EMISC: verr = cdepoterror_EMISC; break; default: verr = cdepoterror; break; } rb_raise(verr, "%s", dperrmsg(ecode)); } static VALUE rbdpopen(VALUE vself, VALUE vname, VALUE vomode, VALUE vbnum){ DEPOT *depot; const char *name; int index, omode, bnum; if((index = getnewindex()) == -1) myerror(DP_EMISC); name = STR2CSTR(vname); FIXNUM_P(vomode); omode = FIX2INT(vomode); FIXNUM_P(vbnum); bnum = FIX2INT(vbnum); if(checkdup(name) == -1) myerror(DP_EMISC); depot = dpopen(name, omode, bnum); if(!depot) myerror(dpecode); dptable[index] = depot; dpsltable[index] = 0; return INT2FIX(index); } static VALUE rbdpclose(VALUE vself, VALUE vindex){ DEPOT *depot; int index; FIXNUM_P(vindex); if((index = FIX2INT(vindex)) == -1) myerror(DP_EMISC); depot = dptable[index]; dptable[index] = NULL; if(!dpclose(depot)) myerror(dpecode); return Qtrue; } static VALUE rbdpsetsilent(VALUE vself, VALUE vindex, VALUE vvalue){ int index; FIXNUM_P(vindex); if((index = FIX2INT(vindex)) == -1) myerror(DP_EMISC); dpsltable[index] = FIX2INT(vvalue); return Qnil; } static VALUE rbdpput(VALUE vself, VALUE vindex, VALUE vkey, VALUE vval, VALUE vdmode){ DEPOT *depot; const char *kbuf, *vbuf; int index, ksiz, vsiz, dmode; FIXNUM_P(vindex); if((index = FIX2INT(vindex)) == -1) myerror(DP_EMISC); kbuf = STR2CSTR(vkey); ksiz = RSTRING(vkey)->len; vbuf = STR2CSTR(vval); vsiz = RSTRING(vval)->len; FIXNUM_P(vdmode); dmode = FIX2INT(vdmode); depot = dptable[index]; if(!dpput(depot, kbuf, ksiz, vbuf, vsiz, dmode)){ if(dpsltable[index] && dpecode == DP_EKEEP) return Qfalse; myerror(dpecode); } return Qtrue; } static VALUE rbdpout(VALUE vself, VALUE vindex, VALUE vkey){ DEPOT *depot; const char *kbuf; int index, ksiz; FIXNUM_P(vindex); if((index = FIX2INT(vindex)) == -1) myerror(DP_EMISC); kbuf = STR2CSTR(vkey); ksiz = RSTRING(vkey)->len; depot = dptable[index]; if(!dpout(depot, kbuf, ksiz)){ if(dpsltable[index] && dpecode == DP_ENOITEM) return Qfalse; myerror(dpecode); } return Qtrue; } static VALUE rbdpget(VALUE vself, VALUE vindex, VALUE vkey, VALUE vstart, VALUE vmax){ DEPOT *depot; const char *kbuf; char *vbuf; int index, ksiz, start, max, vsiz; VALUE vval; FIXNUM_P(vindex); if((index = FIX2INT(vindex)) == -1) myerror(DP_EMISC); kbuf = STR2CSTR(vkey); ksiz = RSTRING(vkey)->len; FIXNUM_P(vstart); start = FIX2INT(vstart); FIXNUM_P(vmax); max = FIX2INT(vmax); depot = dptable[index]; if(!(vbuf = dpget(depot, kbuf, ksiz, start, max, &vsiz))){ if(dpsltable[index] && dpecode == DP_ENOITEM) return Qnil; myerror(dpecode); } vval = rb_str_new(vbuf, vsiz); free(vbuf); return vval; } static VALUE rbdpvsiz(VALUE vself, VALUE vindex, VALUE vkey){ DEPOT *depot; const char *kbuf; int index, ksiz, vsiz; FIXNUM_P(vindex); if((index = FIX2INT(vindex)) == -1) myerror(DP_EMISC); kbuf = STR2CSTR(vkey); ksiz = RSTRING(vkey)->len; depot = dptable[index]; if((vsiz = dpvsiz(depot, kbuf, ksiz)) == -1){ if(dpsltable[index] && dpecode == DP_ENOITEM) return INT2FIX(-1); myerror(dpecode); } return INT2FIX(vsiz); } static VALUE rbdpiterinit(VALUE vself, VALUE vindex){ DEPOT *depot; int index; FIXNUM_P(vindex); if((index = FIX2INT(vindex)) == -1) myerror(DP_EMISC); depot = dptable[index]; if(!dpiterinit(depot)) myerror(dpecode); return Qtrue; } static VALUE rbdpiternext(VALUE vself, VALUE vindex){ DEPOT *depot; char *kbuf; int index, ksiz; VALUE vkey; FIXNUM_P(vindex); if((index = FIX2INT(vindex)) == -1) myerror(DP_EMISC); depot = dptable[index]; if(!(kbuf = dpiternext(depot, &ksiz))){ if(dpsltable[index] && dpecode == DP_ENOITEM) return Qnil; myerror(dpecode); } vkey = rb_str_new(kbuf, ksiz); free(kbuf); return vkey; } static VALUE rbdpsetalign(VALUE vself, VALUE vindex, VALUE valign){ DEPOT *depot; int index, align; FIXNUM_P(vindex); if((index = FIX2INT(vindex)) == -1) myerror(DP_EMISC); FIXNUM_P(valign); align = FIX2INT(valign); depot = dptable[index]; if(!dpsetalign(depot, align)) myerror(dpecode); return Qtrue; } static VALUE rbdpsetfbpsiz(VALUE vself, VALUE vindex, VALUE vsize){ DEPOT *depot; int index, size; FIXNUM_P(vindex); if((index = FIX2INT(vindex)) == -1) myerror(DP_EMISC); FIXNUM_P(vsize); size = FIX2INT(vsize); depot = dptable[index]; if(!dpsetfbpsiz(depot, size)) myerror(dpecode); return Qtrue; } static VALUE rbdpsync(VALUE vself, VALUE vindex){ DEPOT *depot; int index; FIXNUM_P(vindex); if((index = FIX2INT(vindex)) == -1) myerror(DP_EMISC); depot = dptable[index]; if(!dpsync(depot)) myerror(dpecode); return Qtrue; } static VALUE rbdpoptimize(VALUE vself, VALUE vindex, VALUE vbnum){ DEPOT *depot; int index, bnum; FIXNUM_P(vindex); if((index = FIX2INT(vindex)) == -1) myerror(DP_EMISC); FIXNUM_P(vbnum); bnum = FIX2INT(vbnum); depot = dptable[index]; if(!dpoptimize(depot, bnum)) myerror(dpecode); return Qtrue; } static VALUE rbdpfsiz(VALUE vself, VALUE vindex){ DEPOT *depot; int index, fsiz; FIXNUM_P(vindex); if((index = FIX2INT(vindex)) == -1) myerror(DP_EMISC); depot = dptable[index]; if((fsiz = dpfsiz(depot)) == -1) myerror(dpecode); return INT2FIX(fsiz); } static VALUE rbdpbnum(VALUE vself, VALUE vindex){ DEPOT *depot; int index, bnum; FIXNUM_P(vindex); if((index = FIX2INT(vindex)) == -1) myerror(DP_EMISC); depot = dptable[index]; if((bnum = dpbnum(depot)) == -1) myerror(dpecode); return INT2FIX(bnum); } static VALUE rbdprnum(VALUE vself, VALUE vindex){ DEPOT *depot; int index, rnum; FIXNUM_P(vindex); if((index = FIX2INT(vindex)) == -1) myerror(DP_EMISC); depot = dptable[index]; if((rnum = dprnum(depot)) == -1) myerror(dpecode); return INT2FIX(rnum); } static VALUE rbdpwritable(VALUE vself, VALUE vindex){ DEPOT *depot; int index; FIXNUM_P(vindex); if((index = FIX2INT(vindex)) == -1) myerror(DP_EMISC); depot = dptable[index]; return dpwritable(depot) ? Qtrue : Qfalse; } static VALUE rbdpfatalerror(VALUE vself, VALUE vindex){ DEPOT *depot; int index; FIXNUM_P(vindex); if((index = FIX2INT(vindex)) == -1) myerror(DP_EMISC); depot = dptable[index]; return dpfatalerror(depot) ? Qtrue : Qfalse; } /* END OF FILE */ qdbm-1.8.78/ruby/villa/0000755000175000017500000000000010705266455013646 5ustar mikiomikioqdbm-1.8.78/ruby/villa/MANIFEST0000644000175000017500000000006207727054653015002 0ustar mikiomikioMANIFEST extconf.rb villa.rb mod_villa.c rbvltest qdbm-1.8.78/ruby/villa/extconf.rb0000644000175000017500000000070310363125136015627 0ustar mikiomikiorequire 'mkmf' dir_config("villa") home = ENV['HOME'] $CFLAGS = "-I. -I../.. -I#{home}/include -I/usr/local/include" $LDFLAGS = "-L../.. -L#{home}/lib -L/usr/local/lib" $LIBS = "-L../.. -L#{home}/lib -L/usr/local/lib" have_library("c", "main") have_library("pthread", "main") have_library("z", "main") have_library("bz2", "main") have_library("lzo2", "main") have_library("iconv", "main") have_library("qdbm", "main") create_makefile("mod_villa") qdbm-1.8.78/ruby/villa/mod_villa.c0000644000175000017500000005462610505765750015775 0ustar mikiomikio/************************************************************************************************* * Implementation of Villa for Ruby * Copyright (C) 2000-2006 Mikio Hirabayashi * This file is part of QDBM, Quick Database Manager. * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU * Lesser General Public License as published by the Free Software Foundation; either version * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * You should have received a copy of the GNU Lesser General Public License along with QDBM; if * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. *************************************************************************************************/ #include "ruby.h" #include #include #include #include #include #include #include #define MAXOPEN 1024 VALUE cvillaerror; VALUE cvillaerror_ENOERR; VALUE cvillaerror_EFATAL; VALUE cvillaerror_EMODE; VALUE cvillaerror_EBROKEN; VALUE cvillaerror_EKEEP; VALUE cvillaerror_ENOITEM; VALUE cvillaerror_EALLOC; VALUE cvillaerror_EMAP; VALUE cvillaerror_EOPEN; VALUE cvillaerror_ECLOSE; VALUE cvillaerror_ETRUNC; VALUE cvillaerror_ESYNC; VALUE cvillaerror_ESTAT; VALUE cvillaerror_ESEEK; VALUE cvillaerror_EREAD; VALUE cvillaerror_EWRITE; VALUE cvillaerror_ELOCK; VALUE cvillaerror_EUNLINK; VALUE cvillaerror_EMKDIR; VALUE cvillaerror_ERMDIR; VALUE cvillaerror_EMISC; VALUE mvilla; ID idcompare; VILLA *vltable[MAXOPEN]; char vlsltable[MAXOPEN]; static void vlinit(void); static int getnewindex(void); static int checkdup(const char *name); static void myerror(int ecode); static int objcompare(const char *aptr, int asiz, const char *bptr, int bsiz); static VALUE rbvlversion(VALUE vself); static VALUE rbvlerrmsg(VALUE vself, VALUE vecode); static VALUE rbvlopen(VALUE vself, VALUE vname, VALUE vomode, VALUE vcmode); static VALUE rbvlclose(VALUE vself, VALUE vindex); static VALUE rbvlsetsilent(VALUE vself, VALUE vindex, VALUE vvalue); static VALUE rbvlput(VALUE vself, VALUE vindex, VALUE vkey, VALUE vval, VALUE vdmode); static VALUE rbvlout(VALUE vself, VALUE vindex, VALUE vkey); static VALUE rbvlget(VALUE vself, VALUE vindex, VALUE vkey); static VALUE rbvlvsiz(VALUE vself, VALUE vindex, VALUE vkey); static VALUE rbvlvnum(VALUE vself, VALUE vindex, VALUE vkey); static VALUE rbvlcurfirst(VALUE vself, VALUE vindex); static VALUE rbvlcurlast(VALUE vself, VALUE vindex); static VALUE rbvlcurprev(VALUE vself, VALUE vindex); static VALUE rbvlcurnext(VALUE vself, VALUE vindex); static VALUE rbvlcurjump(VALUE vself, VALUE vindex, VALUE vkey, VALUE vjmode); static VALUE rbvlcurkey(VALUE vself, VALUE vindex); static VALUE rbvlcurval(VALUE vself, VALUE vindex); static VALUE rbvlcurput(VALUE vself, VALUE vindex, VALUE vval, VALUE vjmode); static VALUE rbvlcurout(VALUE vself, VALUE vindex); static VALUE rbvlsettuning(VALUE vself, VALUE vindex, VALUE vlrecmax, VALUE vnidxmax, VALUE vlcnum, VALUE vncnum); static VALUE rbvlsync(VALUE vself, VALUE vindex); static VALUE rbvloptimize(VALUE vself, VALUE vindex); static VALUE rbvlfsiz(VALUE vself, VALUE vindex); static VALUE rbvlrnum(VALUE vself, VALUE vindex); static VALUE rbvlwritable(VALUE vself, VALUE vindex); static VALUE rbvlfatalerror(VALUE vself, VALUE vindex); static VALUE rbvltranbegin(VALUE vself, VALUE vindex); static VALUE rbvltrancommit(VALUE vself, VALUE vindex); static VALUE rbvltranabort(VALUE vself, VALUE vindex); /************************************************************************************************* * public objects *************************************************************************************************/ Init_mod_villa(){ vlinit(); cvillaerror = rb_define_class("VillaError", rb_eStandardError); cvillaerror_ENOERR = rb_define_class("VillaError_ENOERR", cvillaerror); cvillaerror_EFATAL = rb_define_class("VillaError_EFATAL", cvillaerror); cvillaerror_EMODE = rb_define_class("VillaError_EMODE", cvillaerror); cvillaerror_EBROKEN = rb_define_class("VillaError_EBROKEN", cvillaerror); cvillaerror_EKEEP = rb_define_class("VillaError_EKEEP", cvillaerror); cvillaerror_ENOITEM = rb_define_class("VillaError_ENOITEM", cvillaerror); cvillaerror_EALLOC = rb_define_class("VillaError_EALLOC", cvillaerror); cvillaerror_EMAP = rb_define_class("VillaError_EMAP", cvillaerror); cvillaerror_EOPEN = rb_define_class("VillaError_EOPEN", cvillaerror); cvillaerror_ECLOSE = rb_define_class("VillaError_ECLOSE", cvillaerror); cvillaerror_ETRUNC = rb_define_class("VillaError_ETRUNC", cvillaerror); cvillaerror_ESYNC = rb_define_class("VillaError_ESYNC", cvillaerror); cvillaerror_ESTAT = rb_define_class("VillaError_ESTAT", cvillaerror); cvillaerror_ESEEK = rb_define_class("VillaError_ESEEK", cvillaerror); cvillaerror_EREAD = rb_define_class("VillaError_EREAD", cvillaerror); cvillaerror_EWRITE = rb_define_class("VillaError_EWRITE", cvillaerror); cvillaerror_ELOCK = rb_define_class("VillaError_ELOCK", cvillaerror); cvillaerror_EUNLINK = rb_define_class("VillaError_EUNLINK", cvillaerror); cvillaerror_EMKDIR = rb_define_class("VillaError_EMKDIR", cvillaerror); cvillaerror_ERMDIR = rb_define_class("VillaError_ERMDIR", cvillaerror); cvillaerror_EMISC = rb_define_class("VillaError_EMISC", cvillaerror); mvilla = rb_define_module("Mod_Villa"); rb_define_const(mvilla, "EANY", cvillaerror); rb_define_const(mvilla, "ENOERR", cvillaerror_ENOERR); rb_define_const(mvilla, "EFATAL", cvillaerror_EFATAL); rb_define_const(mvilla, "EMODE", cvillaerror_EMODE); rb_define_const(mvilla, "EBROKEN", cvillaerror_EBROKEN); rb_define_const(mvilla, "EKEEP", cvillaerror_EKEEP); rb_define_const(mvilla, "ENOITEM", cvillaerror_ENOITEM); rb_define_const(mvilla, "EALLOC", cvillaerror_EALLOC); rb_define_const(mvilla, "EMAP", cvillaerror_EMAP); rb_define_const(mvilla, "EOPEN", cvillaerror_EOPEN); rb_define_const(mvilla, "ECLOSE", cvillaerror_ECLOSE); rb_define_const(mvilla, "ETRUNC", cvillaerror_ETRUNC); rb_define_const(mvilla, "ESYNC", cvillaerror_ESYNC); rb_define_const(mvilla, "ESTAT", cvillaerror_ESTAT); rb_define_const(mvilla, "ESEEK", cvillaerror_ESEEK); rb_define_const(mvilla, "EREAD", cvillaerror_EREAD); rb_define_const(mvilla, "EWRITE", cvillaerror_EWRITE); rb_define_const(mvilla, "ELOCK", cvillaerror_ELOCK); rb_define_const(mvilla, "EUNLINK", cvillaerror_EUNLINK); rb_define_const(mvilla, "EMKDIR", cvillaerror_EMKDIR); rb_define_const(mvilla, "ERMDIR", cvillaerror_ERMDIR); rb_define_const(mvilla, "EMISC", cvillaerror_EMISC); rb_define_const(mvilla, "OREADER", INT2FIX(VL_OREADER)); rb_define_const(mvilla, "OWRITER", INT2FIX(VL_OWRITER)); rb_define_const(mvilla, "OCREAT", INT2FIX(VL_OCREAT)); rb_define_const(mvilla, "OTRUNC", INT2FIX(VL_OTRUNC)); rb_define_const(mvilla, "ONOLCK", INT2FIX(VL_ONOLCK)); rb_define_const(mvilla, "OLCKNB", INT2FIX(VL_OLCKNB)); rb_define_const(mvilla, "OZCOMP", INT2FIX(VL_OZCOMP)); rb_define_const(mvilla, "OYCOMP", INT2FIX(VL_OYCOMP)); rb_define_const(mvilla, "OXCOMP", INT2FIX(VL_OXCOMP)); rb_define_const(mvilla, "CMPLEX", INT2FIX(0)); rb_define_const(mvilla, "CMPDEC", INT2FIX(1)); rb_define_const(mvilla, "CMPOBJ", INT2FIX(2)); rb_define_const(mvilla, "DOVER", INT2FIX(VL_DOVER)); rb_define_const(mvilla, "DKEEP", INT2FIX(VL_DKEEP)); rb_define_const(mvilla, "DCAT", INT2FIX(VL_DCAT)); rb_define_const(mvilla, "DDUP", INT2FIX(VL_DDUP)); rb_define_const(mvilla, "DDUPR", INT2FIX(VL_DDUPR)); rb_define_const(mvilla, "JFORWARD", INT2FIX(VL_JFORWARD)); rb_define_const(mvilla, "JBACKWARD", INT2FIX(VL_JBACKWARD)); rb_define_const(mvilla, "CPCURRENT", INT2FIX(VL_CPCURRENT)); rb_define_const(mvilla, "CPBEFORE", INT2FIX(VL_CPBEFORE)); rb_define_const(mvilla, "CPAFTER", INT2FIX(VL_CPAFTER)); rb_define_module_function(mvilla, "mod_open", rbvlopen, 3); rb_define_module_function(mvilla, "mod_close", rbvlclose, 1); rb_define_module_function(mvilla, "mod_setsilent", rbvlsetsilent, 2); rb_define_module_function(mvilla, "mod_put", rbvlput, 4); rb_define_module_function(mvilla, "mod_out", rbvlout, 2); rb_define_module_function(mvilla, "mod_get", rbvlget, 2); rb_define_module_function(mvilla, "mod_vsiz", rbvlvsiz, 2); rb_define_module_function(mvilla, "mod_vnum", rbvlvnum, 2); rb_define_module_function(mvilla, "mod_curfirst", rbvlcurfirst, 1); rb_define_module_function(mvilla, "mod_curlast", rbvlcurlast, 1); rb_define_module_function(mvilla, "mod_curprev", rbvlcurprev, 1); rb_define_module_function(mvilla, "mod_curnext", rbvlcurnext, 1); rb_define_module_function(mvilla, "mod_curjump", rbvlcurjump, 3); rb_define_module_function(mvilla, "mod_curkey", rbvlcurkey, 1); rb_define_module_function(mvilla, "mod_curval", rbvlcurval, 1); rb_define_module_function(mvilla, "mod_curput", rbvlcurput, 3); rb_define_module_function(mvilla, "mod_curout", rbvlcurout, 1); rb_define_module_function(mvilla, "mod_settuning", rbvlsettuning, 5); rb_define_module_function(mvilla, "mod_sync", rbvlsync, 1); rb_define_module_function(mvilla, "mod_optimize", rbvloptimize, 1); rb_define_module_function(mvilla, "mod_fsiz", rbvlfsiz, 1); rb_define_module_function(mvilla, "mod_rnum", rbvlrnum, 1); rb_define_module_function(mvilla, "mod_writable", rbvlwritable, 1); rb_define_module_function(mvilla, "mod_fatalerror", rbvlfatalerror, 1); rb_define_module_function(mvilla, "mod_tranbegin", rbvltranbegin, 1); rb_define_module_function(mvilla, "mod_trancommit", rbvltrancommit, 1); rb_define_module_function(mvilla, "mod_tranabort", rbvltranabort, 1); rb_eval_string("def Mod_Villa.compare(astr, bstr)\n" " aobj = nil\n" " bobj = nil\n" " begin\n" " aobj = Marshal.load(astr);\n" " rescue\n" " end\n" " begin\n" " bobj = Marshal.load(bstr);\n" " rescue\n" " end\n" " if(aobj && !bobj)\n" " return 1\n" " end\n" " if(!aobj && bobj)\n" " return -1\n" " end\n" " if(!aobj && !bobj)\n" " return 0\n" " end\n" " begin\n" " aobj <=> bobj\n" " rescue\n" " 0\n" " end\n" "end\n"); idcompare = rb_intern("compare"); } /************************************************************************************************* * private objects *************************************************************************************************/ static void vlinit(void){ int i; for(i = 0; i < MAXOPEN; i++){ vltable[i] = NULL; vlsltable[i] = 0; } } static int getnewindex(void){ int i; for(i = 0; i < MAXOPEN; i++){ if(vltable[i] == NULL) return i; } return -1; } static int checkdup(const char *name){ struct stat sbuf; int i, inode; if(stat(name, &sbuf) == -1) return 0; inode = sbuf.st_ino; for(i = 0; i < MAXOPEN; i++){ if(vltable[i] != NULL && vlinode(vltable[i]) == inode) return -1; } return 0; } static void myerror(int ecode){ VALUE verr; switch(ecode){ case DP_ENOERR: verr = cvillaerror_ENOERR; break; case DP_EFATAL: verr = cvillaerror_EFATAL; break; case DP_EMODE: verr = cvillaerror_EMODE; break; case DP_EBROKEN: verr = cvillaerror_EBROKEN; break; case DP_EKEEP: verr = cvillaerror_EKEEP; break; case DP_ENOITEM: verr = cvillaerror_ENOITEM; break; case DP_EALLOC: verr = cvillaerror_EALLOC; break; case DP_EMAP: verr = cvillaerror_EMAP; break; case DP_EOPEN: verr = cvillaerror_EOPEN; break; case DP_ECLOSE: verr = cvillaerror_ECLOSE; break; case DP_ETRUNC: verr = cvillaerror_ETRUNC; break; case DP_ESYNC: verr = cvillaerror_ESYNC; break; case DP_ESTAT: verr = cvillaerror_ESTAT; break; case DP_ESEEK: verr = cvillaerror_ESEEK; break; case DP_EREAD: verr = cvillaerror_EREAD; break; case DP_EWRITE: verr = cvillaerror_EWRITE; break; case DP_ELOCK: verr = cvillaerror_ELOCK; break; case DP_EUNLINK: verr = cvillaerror_EUNLINK; break; case DP_EMKDIR: verr = cvillaerror_EMKDIR; break; case DP_ERMDIR: verr = cvillaerror_ERMDIR; break; case DP_EMISC: verr = cvillaerror_EMISC; break; default: verr = cvillaerror; break; } rb_raise(verr, "%s", dperrmsg(ecode)); } static int objcompare(const char *aptr, int asiz, const char *bptr, int bsiz){ VALUE vastr, vbstr, vret; vastr = rb_str_new(aptr, asiz); vbstr = rb_str_new(bptr, bsiz); vret = rb_funcall(mvilla, idcompare, 2, vastr, vbstr); return FIX2INT(vret); } static VALUE rbvlopen(VALUE vself, VALUE vname, VALUE vomode, VALUE vcmode){ VILLA *villa; const char *name; int index, omode, cmode; VLCFUNC cmp; if((index = getnewindex()) == -1) myerror(DP_EMISC); name = STR2CSTR(vname); FIXNUM_P(vomode); omode = FIX2INT(vomode); FIXNUM_P(vcmode); cmode = FIX2INT(vcmode); cmp = NULL; switch(cmode){ case 0: cmp = VL_CMPLEX; break; case 1: cmp = VL_CMPDEC; break; case 2: cmp = objcompare; break; default: myerror(DP_EMISC); } if(checkdup(name) == -1) myerror(DP_EMISC); villa = vlopen(name, omode, cmp); if(!villa) myerror(dpecode); vltable[index] = villa; vlsltable[index] = 0; return INT2FIX(index); } static VALUE rbvlclose(VALUE vself, VALUE vindex){ VILLA *villa; int index; FIXNUM_P(vindex); if((index = FIX2INT(vindex)) == -1) myerror(DP_EMISC); villa = vltable[index]; vltable[index] = NULL; if(!vlclose(villa)) myerror(dpecode); return Qtrue; } static VALUE rbvlsetsilent(VALUE vself, VALUE vindex, VALUE vvalue){ int index; FIXNUM_P(vindex); if((index = FIX2INT(vindex)) == -1) myerror(DP_EMISC); vlsltable[index] = FIX2INT(vvalue); return Qnil; } static VALUE rbvlput(VALUE vself, VALUE vindex, VALUE vkey, VALUE vval, VALUE vdmode){ VILLA *villa; const char *kbuf, *vbuf; int index, ksiz, vsiz, dmode; FIXNUM_P(vindex); if((index = FIX2INT(vindex)) == -1) myerror(DP_EMISC); kbuf = STR2CSTR(vkey); ksiz = RSTRING(vkey)->len; vbuf = STR2CSTR(vval); vsiz = RSTRING(vval)->len; FIXNUM_P(vdmode); dmode = FIX2INT(vdmode); villa = vltable[index]; if(!vlput(villa, kbuf, ksiz, vbuf, vsiz, dmode)){ if(vlsltable[index] && dpecode == DP_EKEEP) return Qfalse; myerror(dpecode); } return Qtrue; } static VALUE rbvlout(VALUE vself, VALUE vindex, VALUE vkey){ VILLA *villa; const char *kbuf; int index, ksiz; FIXNUM_P(vindex); if((index = FIX2INT(vindex)) == -1) myerror(DP_EMISC); kbuf = STR2CSTR(vkey); ksiz = RSTRING(vkey)->len; villa = vltable[index]; if(!vlout(villa, kbuf, ksiz)){ if(vlsltable[index] && dpecode == DP_ENOITEM) return Qfalse; myerror(dpecode); } return Qtrue; } static VALUE rbvlget(VALUE vself, VALUE vindex, VALUE vkey){ VILLA *villa; const char *kbuf, *vbuf; int index, ksiz, vsiz; VALUE vval; FIXNUM_P(vindex); if((index = FIX2INT(vindex)) == -1) myerror(DP_EMISC); kbuf = STR2CSTR(vkey); ksiz = RSTRING(vkey)->len; villa = vltable[index]; if(!(vbuf = vlget(villa, kbuf, ksiz, &vsiz))){ if(vlsltable[index] && dpecode == DP_ENOITEM) return Qnil; myerror(dpecode); } vval = rb_str_new(vbuf, vsiz); return vval; } static VALUE rbvlvsiz(VALUE vself, VALUE vindex, VALUE vkey){ VILLA *villa; const char *kbuf; int index, ksiz, vsiz; FIXNUM_P(vindex); if((index = FIX2INT(vindex)) == -1) myerror(DP_EMISC); kbuf = STR2CSTR(vkey); ksiz = RSTRING(vkey)->len; villa = vltable[index]; if((vsiz = vlvsiz(villa, kbuf, ksiz)) == -1){ if(vlsltable[index] && dpecode == DP_ENOITEM) return INT2FIX(-1); myerror(dpecode); } return INT2FIX(vsiz); } static VALUE rbvlvnum(VALUE vself, VALUE vindex, VALUE vkey){ VILLA *villa; const char *kbuf; int index, ksiz, vnum; FIXNUM_P(vindex); if((index = FIX2INT(vindex)) == -1) myerror(DP_EMISC); kbuf = STR2CSTR(vkey); ksiz = RSTRING(vkey)->len; villa = vltable[index]; vnum = vlvnum(villa, kbuf, ksiz); return INT2FIX(vnum); } static VALUE rbvlcurfirst(VALUE vself, VALUE vindex){ VILLA *villa; int index; FIXNUM_P(vindex); if((index = FIX2INT(vindex)) == -1) myerror(DP_EMISC); villa = vltable[index]; if(!vlcurfirst(villa)){ if(vlsltable[index] && dpecode == DP_ENOITEM) return Qfalse; myerror(dpecode); } return Qtrue; } static VALUE rbvlcurlast(VALUE vself, VALUE vindex){ VILLA *villa; int index; FIXNUM_P(vindex); if((index = FIX2INT(vindex)) == -1) myerror(DP_EMISC); villa = vltable[index]; if(!vlcurlast(villa)){ if(vlsltable[index] && dpecode == DP_ENOITEM) return Qfalse; myerror(dpecode); } return Qtrue; } static VALUE rbvlcurprev(VALUE vself, VALUE vindex){ VILLA *villa; int index; FIXNUM_P(vindex); if((index = FIX2INT(vindex)) == -1) myerror(DP_EMISC); villa = vltable[index]; if(!vlcurprev(villa)){ if(vlsltable[index] && dpecode == DP_ENOITEM) return Qfalse; myerror(dpecode); } return Qtrue; } static VALUE rbvlcurnext(VALUE vself, VALUE vindex){ VILLA *villa; int index; FIXNUM_P(vindex); if((index = FIX2INT(vindex)) == -1) myerror(DP_EMISC); villa = vltable[index]; if(!vlcurnext(villa)){ if(vlsltable[index] && dpecode == DP_ENOITEM) return Qfalse; myerror(dpecode); } return Qtrue; } static VALUE rbvlcurjump(VALUE vself, VALUE vindex, VALUE vkey, VALUE vjmode){ VILLA *villa; const char *kbuf; int index, ksiz, jmode; VALUE vval; FIXNUM_P(vindex); if((index = FIX2INT(vindex)) == -1) myerror(DP_EMISC); kbuf = STR2CSTR(vkey); ksiz = RSTRING(vkey)->len; FIXNUM_P(vjmode); jmode = FIX2INT(vjmode); villa = vltable[index]; if(!vlcurjump(villa, kbuf, ksiz, jmode)){ if(vlsltable[index] && dpecode == DP_ENOITEM) return Qfalse; myerror(dpecode); } return Qtrue; } static VALUE rbvlcurkey(VALUE vself, VALUE vindex){ VILLA *villa; const char *kbuf; int index, ksiz; VALUE vkey; FIXNUM_P(vindex); if((index = FIX2INT(vindex)) == -1) myerror(DP_EMISC); villa = vltable[index]; if(!(kbuf = vlcurkeycache(villa, &ksiz))){ if(vlsltable[index] && dpecode == DP_ENOITEM) return Qnil; myerror(dpecode); } vkey = rb_str_new(kbuf, ksiz); return vkey; } static VALUE rbvlcurval(VALUE vself, VALUE vindex){ VILLA *villa; const char *vbuf; int index, vsiz; VALUE vval; FIXNUM_P(vindex); if((index = FIX2INT(vindex)) == -1) myerror(DP_EMISC); villa = vltable[index]; if(!(vbuf = vlcurvalcache(villa, &vsiz))){ if(vlsltable[index] && dpecode == DP_ENOITEM) return Qnil; myerror(dpecode); } vval = rb_str_new(vbuf, vsiz); return vval; } static VALUE rbvlcurput(VALUE vself, VALUE vindex, VALUE vval, VALUE vcpmode){ VILLA *villa; const char *vbuf; int index, vsiz, cpmode; FIXNUM_P(vindex); if((index = FIX2INT(vindex)) == -1) myerror(DP_EMISC); vbuf = STR2CSTR(vval); vsiz = RSTRING(vval)->len; FIXNUM_P(vcpmode); cpmode = FIX2INT(vcpmode); villa = vltable[index]; if(!vlcurput(villa, vbuf, vsiz, cpmode)){ if(vlsltable[index] && dpecode == DP_ENOITEM) return Qfalse; myerror(dpecode); } return Qtrue; } static VALUE rbvlcurout(VALUE vself, VALUE vindex){ VILLA *villa; int index; FIXNUM_P(vindex); if((index = FIX2INT(vindex)) == -1) myerror(DP_EMISC); villa = vltable[index]; if(!vlcurout(villa)){ if(vlsltable[index] && dpecode == DP_ENOITEM) return Qfalse; myerror(dpecode); } return Qtrue; } static VALUE rbvlsettuning(VALUE vself, VALUE vindex, VALUE vlrecmax, VALUE vnidxmax, VALUE vlcnum, VALUE vncnum){ VILLA *villa; int index, lrecmax, nidxmax, lcnum, ncnum; FIXNUM_P(vindex); if((index = FIX2INT(vindex)) == -1) myerror(DP_EMISC); FIXNUM_P(vlrecmax); lrecmax = FIX2INT(vlrecmax); FIXNUM_P(vnidxmax); nidxmax = FIX2INT(vnidxmax); FIXNUM_P(vlcnum); lcnum = FIX2INT(vlcnum); FIXNUM_P(vncnum); ncnum = FIX2INT(vncnum); villa = vltable[index]; vlsettuning(villa, lrecmax, nidxmax, lcnum, ncnum); return Qtrue; } static VALUE rbvlsync(VALUE vself, VALUE vindex){ VILLA *villa; int index; FIXNUM_P(vindex); if((index = FIX2INT(vindex)) == -1) myerror(DP_EMISC); villa = vltable[index]; if(!vlsync(villa)) myerror(dpecode); return Qtrue; } static VALUE rbvloptimize(VALUE vself, VALUE vindex){ VILLA *villa; int index; FIXNUM_P(vindex); if((index = FIX2INT(vindex)) == -1) myerror(DP_EMISC); villa = vltable[index]; if(!vloptimize(villa)) myerror(dpecode); return Qtrue; } static VALUE rbvlfsiz(VALUE vself, VALUE vindex){ VILLA *villa; int index, fsiz; FIXNUM_P(vindex); if((index = FIX2INT(vindex)) == -1) myerror(DP_EMISC); villa = vltable[index]; if((fsiz = vlfsiz(villa)) == -1) myerror(dpecode); return INT2FIX(fsiz); } static VALUE rbvlrnum(VALUE vself, VALUE vindex){ VILLA *villa; int index, rnum; FIXNUM_P(vindex); if((index = FIX2INT(vindex)) == -1) myerror(DP_EMISC); villa = vltable[index]; if((rnum = vlrnum(villa)) == -1) myerror(dpecode); return INT2FIX(rnum); } static VALUE rbvlwritable(VALUE vself, VALUE vindex){ VILLA *villa; int index; FIXNUM_P(vindex); if((index = FIX2INT(vindex)) == -1) myerror(DP_EMISC); villa = vltable[index]; return vlwritable(villa) ? Qtrue : Qfalse; } static VALUE rbvlfatalerror(VALUE vself, VALUE vindex){ VILLA *villa; int index; FIXNUM_P(vindex); if((index = FIX2INT(vindex)) == -1) myerror(DP_EMISC); villa = vltable[index]; return vlfatalerror(villa) ? Qtrue : Qfalse; } static VALUE rbvltranbegin(VALUE vself, VALUE vindex){ VILLA *villa; int index; FIXNUM_P(vindex); if((index = FIX2INT(vindex)) == -1) myerror(DP_EMISC); villa = vltable[index]; if(!vltranbegin(villa)) myerror(dpecode); return Qtrue; } static VALUE rbvltrancommit(VALUE vself, VALUE vindex){ VILLA *villa; int index; FIXNUM_P(vindex); if((index = FIX2INT(vindex)) == -1) myerror(DP_EMISC); villa = vltable[index]; if(!vltrancommit(villa)) myerror(dpecode); return Qtrue; } static VALUE rbvltranabort(VALUE vself, VALUE vindex){ VILLA *villa; int index; FIXNUM_P(vindex); if((index = FIX2INT(vindex)) == -1) myerror(DP_EMISC); villa = vltable[index]; if(!vltranabort(villa)) myerror(dpecode); return Qtrue; } /* END OF FILE */ qdbm-1.8.78/ruby/villa/lib/0000755000175000017500000000000010540430442014376 5ustar mikiomikioqdbm-1.8.78/ruby/villa/lib/villa.rb0000644000175000017500000006534510540430370016047 0ustar mikiomikio#================================================================================================= # Ruby API of Villa, the advanced API of QDBM # Copyright (C) 2000-2006 Mikio Hirabayashi # This file is part of QDBM, Quick Database Manager. # QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU # Lesser General Public License as published by the Free Software Foundation; either version # 2.1 of the License or any later version. QDBM is distributed in the hope that it will be # useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more # details. # You should have received a copy of the GNU Lesser General Public License along with QDBM; if # not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA # 02111-1307 USA. #================================================================================================= require 'mod_villa' require 'thread' ## # require 'villa' # The library `villa' should be included in application codes. # An instance of the class `Villa' is used as a database handle. # `Villa' performs Mix-in of `Enumerable'. # Each method of `Villa' throws an exception of `Villa::EANY' or its sub classes when an error # occurs: `Villa::ENOERR', `Villa::EFATAL', `Villa::EMODE', `Villa::EBROKEN', `Villa::EKEEP', # `Villa::ENOITEM', `Villa::EALLOC', `Villa::EMAP', `Villa::EOPEN', `Villa::ECLOSE', # `Villa::ETRUNC', `Villa::ESYNC', `Villa::ESTAT', `Villa::ESEEK', `Villa::EREAD', # `Villa::EWRITE', `Villa::ELOCK', `Villa::EUNLINK', `Villa::EMKDIR', `Villa::ERMDIR' and # `Villa::EMISC'. # class Villa include Mod_Villa, Enumerable #---------------------------------------------------------------- # class constants #---------------------------------------------------------------- MyMutex = Mutex::new() #---------------------------------------------------------------- # class methods #---------------------------------------------------------------- public ## # villa = Villa::new(name, omode, cmode) # Constructor: Get a database handle. # `name' specifies the name of a database file. # `omode' specifies the connection mode: `Villa::OWRITER' as a writer, `Villa::OREADER' as a # reader. If the mode is `Villa::OWRITER', the following may be added by bitwise or: # `Villa::OCREAT', which means it creates a new database if not exist, `Villa::OTRUNC', which # means it creates a new database regardless if one exists, `Villa::OZCOMP', which means # leaves in the database are compressed with ZLIB, `Villa::OYCOMP', which means leaves in the # database are compressed with LZO, `Villa::OXCOMP', which means leaves in the database are # compressed with BZIP2. Both of `Villa::OREADER' and `Villa::OWRITER' can be added to by # bitwise or: `Villa::ONOLCK', which means it opens a database file without file locking, or # `Villa::OLCKNB', which means locking is performed without blocking. If it is omitted, # `Villa::OREADER' is specified. # `cmode' specifies the comparing function: `Villa::CMPLEX' comparing keys in lexical order, # `Villa::CMPDEC' comparing keys as decimal strings, `Villa::CMPOBJ' comparing keys as # serialized objects implementing the method `<=>'. The comparing function should be kept # same in the life of a database. If `Villa::CMPOBJ' is used, such methods as `put', `out', # `get' and so on can treat not only instances of `String' but also any serializable and # comparable object. # If so, objects being stored are serialized and objects being retrieved are deserialized. # The return value is the database handle. # An exception of `Villa::EANY' or its sub classes is thrown if an error occurs. # If a block parameter is given, this method works as an iterator. A database handle is # opened and passed via the first argument of the block. The database handle is surely # closed when the block is over. # While connecting as a writer, an exclusive lock is invoked to the database file. # While connecting as a reader, a shared lock is invoked to the database file. The thread # blocks until the lock is achieved. `Villa::OZCOMP', `Villa::OYCOMP', and `Villa::OXCOMP' # are available only if QDBM was built each with ZLIB, LZO, and BZIP2 enabled. If # `Villa::ONOLCK' is used, the application is responsible for exclusion control. # #@ DEFINED IMPLICITLY ## # villa = Villa::open(name, omode, cmode) # Constructor: An alias of `new'. # #@ DEFINED OUTSIDE #---------------------------------------------------------------- # private methods #---------------------------------------------------------------- private #= # initialize(name, omode, cmode) # Method: Called implicitly by the constructor. # def initialize(name, omode = OREADER, cmode = CMPLEX) @silent = false MyMutex.synchronize() do @index = mod_open(name, omode, cmode) @name = name @cmode = cmode @tranmutex = Mutex::new() end if(iterator?) begin yield(self) ensure close() end end self end #= # clone() # Method: Forbidden to use. # def clone raise(VillaError) end #= # dup() # Method: Forbidden to use. # alias dup clone #---------------------------------------------------------------- # public methods #---------------------------------------------------------------- public ## # bool = villa.close() # Method: Close the database handle. # The return value is always true. # An exception of `Villa::EANY' or its sub classes is thrown if an error occurs. # Because the region of a closed handle is released, it becomes impossible to use the handle. # Updating a database is assured to be written when the handle is closed. If a writer opens # a database but does not close it appropriately, the database will be broken. If the # transaction is activated and not committed, it is aborted. # def close() MyMutex.synchronize() do begin mod_close(@index) ensure @index = -1 end end end ## # villa.silent = bool # Method: Set the flag whether to repress frequent exceptions. # The return value is the assigned value. # def silent=(value) @silent = value ? true : false mod_setsilent(@index, silent ? 1 : 0) @silent end def silent @silent end ## # bool = villa.put(key, val, dmode) # Method: Store a record. # `key' specifies a key. Although it must be an instance of String, binary data is okey. # `val' specifies a value. Although it must be an instance of String, binary data is okey. # `dmode' specifies behavior when the key overlaps, by the following values: `Villa::DOVER', # which means the specified value overwrites the existing one, `Villa::DKEEP', which means the # existing value is kept, `Villa::DCAT', which means the specified value is concatenated at the # end of the existing value, `Villa::DDUP', which means duplication of keys is allowed and the # specified value is added as the last one, `Villa::DDUPR', which means duplication of keys is # allowed and the specified value is added as the first one. If it is omitted, `Villa::DOVER' # is specified. # The return value is always true. However, if the silent flag is true and replace is # cancelled, false is returned instead of exception. # An exception of `Villa::EANY' or its sub classes is thrown if an error occurs or replace # is cancelled. # The cursor becomes unavailable due to updating database. # def put(key, val, dmode = DOVER) if(@cmode == CMPOBJ) key = Marshal.dump(key) val = Marshal.dump(val) end mod_put(@index, key, val, dmode) end ## # bool = villa.store(key, val) # Method: An alias of `put'. # alias store put ## # villa[key] = val # Method: An alias of `put'. # alias []= put ## # bool = villa.out(key) # Method: Delete a record. # `key' specifies a key. Although it must be an instance of String, binary data is okey. # The return value is always true. However, if the silent flag is true and no record # corresponds, false is returned instead of exception. # An exception of `Villa::EANY' or its sub classes is thrown if an error occurs or no record # corresponds. # When the key of duplicated records is specified, the value of the first record of the same # key is selected. The cursor becomes unavailable due to updating database. # def out(key) if(@cmode == CMPOBJ) key = Marshal.dump(key) end mod_out(@index, key) end ## # bool = villa.delete(key) # Method: An alias of `out'. # alias delete out ## # bool = villa.clear() # Method: Delete all records. # The return value is always true. # An exception of `Villa::EANY' or its sub classes is thrown if an error occurs. # def clear MyMutex.synchronize() do begin while(rnum() > 0) curfirst(); out(curkey()) end rescue ENOITEM end end true end ## # str = villa.get(key) # Method: Retrieve a record. # `key' specifies a key. Although it must be an instance of String, binary data is okey. # The return value is an instance of the value of the corresponding record. If the silent flag # is true and no record corresponds, nil is returned instead of exception. # When the key of duplicated records is specified, the first record of the same key is # deleted. # An exception of `Villa::EANY' or its sub classes is thrown if an error occurs or no record # corresponds. # def get(key) if(@cmode == CMPOBJ) key = Marshal.dump(key) end val = mod_get(@index, key) if(@cmode == CMPOBJ && val) val = Marshal.load(val) end val end ## # str = villa.fetch(key, defval) # Method: Retrieve a record. # `key' specifies a key. Although it must be an instance of String, binary data is okey. # `defval' specifies the default value used when no record corresponds. If it is omitted, nil # is specified. # The return value is an instance of the value of the corresponding record, or the default # value if no record corresponds. # An exception of `Villa::EANY' or its sub classes is thrown if an error occurs. # def fetch(key, defval = nil) if @silent if val = mod_get(@index, key) if(@cmode == CMPOBJ) val = Marshal.load(val) end val else defval end else begin val = mod_get(@index, key) if(@cmode == CMPOBJ) val = Marshal.load(val) end val rescue ENOITEM defval end end end ## # str = villa[key] # Method: An alias of `fetch'. # alias [] fetch ## # num = villa.vsiz(key) # Method: Get the size of the value of a record. # `key' specifies a key. Although it must be an instance of String, binary data is okey. # The return value is the size of the value of the corresponding record. If the silent flag # is true and no record corresponds, -1 is returned instead of exception. If multiple records # correspond, the size of the first is returned. # An exception of `Villa::EANY' or its sub classes is thrown if an error occurs. # def vsiz(key) if(@cmode == CMPOBJ) key = Marshal.dump(key) end mod_vsiz(@index, key) end ## # num = villa.vnum(key) # Method: Get the number of records corresponding a key. # `key' specifies a key. Although it must be an instance of String, binary data is okey. # The return value is the size of the value of the corresponding record. If no record # corresponds, 0 is returned. # An exception of `Villa::EANY' or its sub classes is thrown if an error occurs. # def vnum(key) if(@cmode == CMPOBJ) key = Marshal.dump(key) end mod_vnum(@index, key) end ## # bool = villa.curfirst() # Method: Move the cursor to the first record. # The return value is always true. However, if the silent flag is true and no record # corresponds, false is returned instead of exception. # An exception of `Villa::EANY' or its sub classes is thrown if an error occurs or there is # no record in the database. # def curfirst() mod_curfirst(@index) end ## # bool = villa.curlast() # Method: Move the cursor to the last record. # The return value is always true. However, if the silent flag is true and no record # corresponds, false is returned instead of exception. # An exception of `Villa::EANY' or its sub classes is thrown if an error occurs or there is # no record in the database. # def curlast() mod_curlast(@index) end ## # bool = villa.curprev() # Method: Move the cursor to the previous record. # The return value is always true. However, if the silent flag is true and no record # corresponds, false is returned instead of exception. # An exception of `Villa::EANY' or its sub classes is thrown if an error occurs or there is # no previous record. # def curprev() mod_curprev(@index) end ## # bool = villa.curnext() # Method: Move the cursor to the next record. # The return value is always true. However, if the silent flag is true and no record # corresponds, false is returned instead of exception. # An exception of `Villa::EANY' or its sub classes is thrown if an error occurs or there is # no next record. # def curnext() mod_curnext(@index) end ## # bool = villa.curjump(key, jmode) # Method: Move the cursor to a position around a record. # `key' specifies a key. Although it must be an instance of String, binary data is okey. # `jmode' specifies detail adjustment: `Villa::JFORWARD', which means that the cursor is set # to the first record of the same key and that the cursor is set to the next substitute if # completely matching record does not exist, `Villa::JBACKWARD', which means that the cursor # is set to the last record of the same key and that the cursor is set to the previous # substitute if completely matching record does not exist. If it is omitted, `Villa::JFORWARD' # is specified. # The return value is always true. However, if the silent flag is true and no record # corresponds, false is returned instead of exception. # An exception of `Villa::EANY' or its sub classes is thrown if an error occurs or there is # no record corresponding the condition. # def curjump(key, jmode = JFORWARD) if(@cmode == CMPOBJ) key = Marshal.dump(key) end mod_curjump(@index, key, jmode) end ## # str = villa.curkey() # Method: Get the key of the record where the cursor is. # The return value is the key of the corresponding record. If the silent flag is true and no # record corresponds, nil is returned instead of exception. # An exception of `Villa::EANY' or its sub classes is thrown if an error occurs or no record # corresponds to the cursor. # def curkey() key = mod_curkey(@index) if(@cmode == CMPOBJ && key) key = Marshal.load(key) end key end ## # str = villa.curval() # Method: Get the value of the record where the cursor is. # The return value is the value of the corresponding record. If the silent flag is true and no # record corresponds, nil is returned instead of exception. # An exception of `Villa::EANY' or its sub classes is thrown if an error occurs or no record # corresponds to the cursor. # def curval() val = mod_curval(@index) if(@cmode == CMPOBJ && val) val = Marshal.load(val) end val end ## # bool = villa.curput(val, cpmode); # Method: Insert a record around the cursor. # `val' specifies a value. Although it must be an instance of String, binary data is okey. # `cpmode' specifies detail adjustment: `Villa::CPCURRENT', which means that the value of the # current record is overwritten, `Villa::CPBEFORE', which means that a new record is inserted # before the current record, `Villa::CPAFTER', which means that a new record is inserted after # the current record. If it is omitted, `Villa::CPCURRENT' is specified. # The return value is always true. However, if the silent flag is true and no record # corresponds to the cursor, false is returned instead of exception. # An exception of `Villa::EANY' or its sub classes is thrown if an error occurs or no record # corresponds to the cursor. # After insertion, the cursor is moved to the inserted record. # def curput(val, cpmode = CPCURRENT) if(@cmode == CMPOBJ) val = Marshal.dump(val) end mod_curput(@index, val, cpmode) end ## # bool = villa.curout(); # Method: Delete the record where the cursor is. # The return value is always true. However, if the silent flag is true and no record # corresponds to the cursor, false is returned instead of exception. # An exception of `Villa::EANY' or its sub classes is thrown if an error occurs or no record # corresponds to the cursor. # After deletion, the cursor is moved to the next record if possible. # def curout() mod_curout(@index) end ## # bool = villa.settuning(lrecmax, nidxmax, lcnum, ncnum) # Method: Set the tuning parameters for performance. # `lrecmax' specifies the max number of records in a leaf node of B+ tree. If it is not more # than 0, the default value is specified. # `nidxmax' specifies the max number of indexes in a non-leaf node of B+ tree. If it is not # more than 0, the default value is specified. # `lcnum' specifies the max number of caching leaf nodes. If it is not more than 0, the # default value is specified. # `ncnum' specifies the max number of caching non-leaf nodes. If it is not more than 0, the # default value is specified. # The return value is always true. # An exception of `Villa::EANY' or its sub classes is thrown if an error occurs. # The default setting is equivalent to `vlsettuning(49, 192, 1024, 512)'. Because tuning # parameters are not saved in a database, you should specify them every opening a database. # def settuning(lrecmax, nidxmax, lcnum, ncnum) mod_settuning(@index, lrecmax, nidxmax, lcnum, ncnum) end ## # bool = villa.sync() # Method: Synchronize updating contents with the file and the device. # The return value is always true. # An exception of `Villa::EANY' or its sub classes is thrown if an error occurs. # This method is useful when another process uses the connected database file. This method # should not be used while the transaction is activated. # def sync() mod_sync(@index) end ## # bool = villa.optimize() # Method: Optimize the database. # The return value is always true. # An exception of `Villa::EANY' or its sub classes is thrown if an error occurs. # In an alternating succession of deleting and storing with overwrite or concatenate, # dispensable regions accumulate. This method is useful to do away with them. This method # should not be used while the transaction is activated. # def optimize() mod_optimize(@index) end ## # num = villa.fsiz() # Method: Get the size of the database file. # The return value is the size of the database file. # An exception of `Villa::EANY' or its sub classes is thrown if an error occurs. # Because of the I/O buffer, the return value may be less than the real size. # def fsiz() mod_fsiz(@index) end ## # num = villa.rnum() # Method: Get the number of the records stored in the database. # The return value is the number of the records stored in the database. # An exception of `Villa::EANY' or its sub classes is thrown if an error occurs. # def rnum() mod_rnum(@index) end ## # num = villa.length() # Method: An alias of `rnum'. # alias length rnum ## # num = villa.size() # Method: An alias of `rnum'. # alias size rnum ## # bool = villa.writable() # Method: Check whether the database handle is a writer or not. # The return value is true if the handle is a writer, false if not. # An exception of `Villa::EANY' or its sub classes is thrown if an error occurs. # def writable() mod_writable(@index) end ## # bool = villa.fatalerror() # Method: Check whether the database has a fatal error or not. # The return value is true if the database has a fatal error, false if not. # An exception of `Villa::EANY' or its sub classes is thrown if an error occurs. # def fatalerror() mod_fatalerror(@index) end ## # bool = villa.tranbegin() # Method: Begin the transaction. # The return value is always true. # An exception of `Villa::EANY' or its sub classes is thrown if an error occurs. # If a thread is already in the transaction, the other threads block until the prius is out # of the transaction. Only one transaction can be activated with a database handle at the # same time. # def tranbegin() @tranmutex.lock() MyMutex.synchronize() do begin mod_tranbegin(@index) rescue @tranmutex.unlock() raise() end end end ## # bool = villa.trancommit() # Method: Commit the transaction. # The return value is always true. # An exception of `Villa::EANY' or its sub classes is thrown if an error occurs. # Updating a database in the transaction is fixed when it is committed successfully. Any # other thread except for the one which began the transaction should not call this method. # def trancommit() begin mod_trancommit(@index) ensure @tranmutex.unlock() end end ## # bool = villa.tranabort() # Method: Abort the transaction. # The return value is always true. # An exception of `Villa::EANY' or its sub classes is thrown if an error occurs. # Updating a database in the transaction is discarded when it is aborted. The state of the # database is rollbacked to before transaction. Any other thread except for the one which # began the transaction should not call this method. # def tranabort() begin mod_tranabort(@index) ensure @tranmutex.unlock() end end ## # villa.transaction() do ... end # Iterator Method: Perform an iterator block in the transaction. # The specified iterator block is performed in the transaction. If the block returns true, # the transaction is committed. If the block returns false or raises any exception, the # transaction is aborted. # def transaction() tranbegin() begin cmt = yield() rescue cmt = false raise() ensure if(cmt) trancommit() else tranabort() end end end ## # villa.each() do |key, val| ... end # Iterator Method: Iterate a process with a pair of a key and a value of each record. # def each() MyMutex.synchronize() do curfirst() while(true) begin break unless key = curkey() val = curval() yield(key, val) curnext() rescue ENOITEM break end end curfirst() end self end ## # villa.each_pair() do |key, val| ... end # Iterator Method: An alias of `each'. # alias each_pair each ## # villa.each_key() do |key| ... end # Iterator Method: Iterate a process with a key of each record. # def each_key() MyMutex.synchronize() do curfirst() while(true) begin break unless key = curkey() curnext() yield(key) rescue ENOITEM break end end curfirst() end self end ## # villa.each_value() do |val| ... end # Iterator Method: Iterate a process with a value of each record. # def each_value() MyMutex.synchronize() do curfirst() while(true) begin break unless val = curval() curnext() yield(val) rescue ENOITEM break end end curfirst() end self end ## # ary = villa.keys() # Method: Get an array of all keys. # The return value is an array of all keys. # An exception of `Villa::EANY' or its sub classes is thrown if an error occurs. # def keys() ary = Array::new(rnum()) MyMutex.synchronize() do begin curfirst() 0.upto(ary.length - 1) do |i| ary[i] = curkey() curnext() end curfirst() rescue ENOITEM end end ary end ## # ary = villa.values() # Method: Get an array of all values. # The return value is an array of all values. # An exception of `Villa::EANY' or its sub classes is thrown if an error occurs. # def values() ary = Array::new(rnum()) MyMutex.synchronize() do begin curfirst() 0.upto(ary.length - 1) do |i| ary[i] = curval() curnext() end curfirst() rescue ENOITEM end end ary end ## # str = villa.index(val) # Method: Retrieve a record with a value. # `val' specifies a value. Although it must be an instance of String, binary data is okey. # The return value is the key of the record with the specified value. # An exception of `Villa::EANY' or its sub classes is thrown if an error occurs or no record # corresponds. # If two or more records correspond, the first found record is selected. # def index(val) key = nil MyMutex.synchronize() do curfirst() while(true) break unless tmp = curval() if(tmp == val) key = curkey() break end curnext() end curfirst() end key end ## # num = villa.to_int() # Method: An alias of `rnum'. # alias to_int rnum ## # num = villa.to_i() # Method: An alias of `to_int'. # alias to_i to_int ## # str = villa.to_str() # Method: Get string standing for the instance. # def to_str if(@index != -1) sprintf("#", object_id(), @name, rnum()) else sprintf("#", object_id(), @name) end end ## # str = villa.to_s() # Method: An alias of `to_str'. # alias to_s to_str ## # ary = villa.to_ary() # Method: Get an array of alternation of each pair of a key and a value. # def to_ary ary = Array::new(rnum()) i = 0 each() do |key, val| ary[i] = [key, val] i += 1 end ary end ## # ary = villa.to_a() # Method: An alias of `to_ary'. # alias to_a to_ary ## # hash = villa.to_hash() # Method: Get a hash storing all records. # def to_hash hash = Hash::new() each() do |key, val| hash[key] || hash[key] = val end hash end ## # hash = villa.to_h() # Method: An alias of `to_hash'. # alias to_h to_hash ## # str = villa.inspect() # Method: An alias of `to_str'. # alias inspect to_str end #---------------------------------------------------------------- # Alias definition of class methods #---------------------------------------------------------------- class << Villa alias open new end # END OF FILE qdbm-1.8.78/ruby/villa/rbvltest0000755000175000017500000001476510505770134015446 0ustar mikiomikio#! /usr/bin/ruby -w #================================================================================================= # Test cases of Villa for Ruby # Copyright (C) 2000-2005 Mikio Hirabayashi # This file is part of QDBM, Quick Database Manager. # QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU # Lesser General Public License as published by the Free Software Foundation; either version # 2.1 of the License or any later version. QDBM is distributed in the hope that it will be # useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more # details. # You should have received a copy of the GNU Lesser General Public License along with QDBM; if # not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA # 02111-1307 USA. #================================================================================================= require 'villa' # main routine def main() $0.gsub!(/.*\//, "") (ARGV.length >= 1) || usage() if(ARGV[0] == "write") rv = runwrite() elsif(ARGV[0] == "read") rv = runread() elsif(ARGV[0] == "misc") rv = runmisc() else usage() end return rv end # print the usage and exit def usage() printf(STDERR, "%s: test cases for Villa for Ruby\n", $0) printf(STDERR, "\n") printf(STDERR, "usage:\n") printf(STDERR, " %s write name rnum\n", $0) printf(STDERR, " %s read name\n", $0) printf(STDERR, " %s misc name\n", $0) printf(STDERR, "\n") exit(1) end # parse arguments of write command def runwrite() name = nil rnum = -1 i = 1 while(i < ARGV.length) if(!name && ARGV[i] =~ /^-/) usage() elsif(!name) name = ARGV[i] elsif(rnum < 0) rnum = ARGV[i].to_i() else usage() end i += 1 end (name && rnum > 0) || usage() dowrite(name, rnum) return 0 end # parse arguments of read command def runread() name = nil i = 1 while(i < ARGV.length) if(!name && ARGV[i] =~ /^-/) usage() elsif(!name) name = ARGV[i] else usage() end i += 1 end (name) || usage() doread(name) return 0 end # parse arguments of misc command def runmisc() name = nil i = 1 while(i < ARGV.length) if(!name && ARGV[i] =~ /^-/) usage() elsif(!name) name = ARGV[i] else usage() end i += 1 end (name) || usage() domisc(name) return 0 end # perform write command def dowrite(name, rnum) printf("\n name=%s rnum=%d\n\n", name, rnum) villa = nil begin # open a database villa = Villa::new(name, Villa::OWRITER | Villa::OCREAT | Villa::OTRUNC) # loop for each record STDOUT.sync = true 1.upto(rnum) do |i| buf = sprintf("%08d", i) # store a record villa.put(buf, buf) # print progression if(rnum > 250 && i % (rnum / 250) == 0) print(".") if(i == rnum || i % (rnum / 10) == 0) printf(" (%08d)\n", i) end end end rescue printf("%s: %s: %s\n", $0, name, $!) return 1 ensure begin # close the database (villa) && villa.close() rescue return 1 end end printf("ok\n\n") return 0 end # perform read command def doread(name) printf("\n name=%s\n\n", name) villa = nil begin # open a database villa = Villa::new(name) # get the number of record rnum = villa.rnum() # loop for each record STDOUT.sync = true 1.upto(rnum) do |i| buf = sprintf("%08d", i) # store a record villa.get(buf) # print progression if(rnum > 250 && i % (rnum / 250) == 0) print(".") if(i == rnum || i % (rnum / 10) == 0) printf(" (%08d)\n", i) end end end rescue printf("%s: %s: %s\n", $0, name, $!) return 1 ensure begin # close the database (villa) && villa.close() rescue return 1 end end printf("ok\n\n") return 0 end # perform misc command def domisc(name) loopnum = 500 threadnum = 10 printf("\n name=%s\n\n", name) villa = nil begin # open the database printf("Creating a database ... ") villa = Villa::open("casket", Villa::OWRITER | Villa::OCREAT | Villa::OTRUNC) printf("ok\n") # store records printf("Storing records ... ") 1.upto(loopnum) do |i| buf = sprintf("%08d", i) villa[buf] = buf end printf("ok\n") # retrieve records printf("Retrieving records ... ") 1.upto(loopnum) do |i| buf = sprintf("%08d", i) (villa[buf] == buf) || raise("key and value does not match") end printf("ok\n") # traverse records printf("Traversing records ... ") villa.each() do |key, val| (key == val) || raise("key and value does not match") end villa.keys() villa.values() printf("ok\n") # silent mode operations printf("Silent mode operations ... ") villa.silent = true villa.put("foo", "bar", Villa::DKEEP) villa.put("foo", "bar", Villa::DKEEP) villa.get("foo") villa.out("foo") villa.out("foo") villa.get("nil") villa.fetch("nil", "void"); villa.keys() villa.values() printf("ok\n") rescue printf("%s: %s: %s\n", $0, name, $!) return 1 ensure # close the database printf("Closing the database ... ") (villa) && villa.close() printf("ok\n") end # test iterator and threads printf("Processing with iterator, threads and transactions ... ") Villa::new("casket", Villa::OWRITER) do |villa| (villa.rnum() == loopnum) || raise("record number is invalid") villa.clear() threads = [] 1.upto(threadnum) do |i| t = Thread::new() do 1.upto(loopnum) do |j| buf = sprintf("%08d", j) villa.put(buf, "*", Villa::DDUP) end villa.tranbegin() 1.upto(loopnum) do |j| buf = sprintf("%08d", j) villa.put(buf, "*", Villa::DDUP) end villa.trancommit() end threads.push(t) end threads.each do |t| t.join() end 1.upto(loopnum) do |i| buf = sprintf("%08d", i) (villa.vnum(buf) == threadnum * 2) || raise("thread writing is invalid") end (villa.index("*")) || raise("thread writing is invalid") end printf("ok\n") printf("all ok\n\n") return 0 end # execute main $0.gsub!(/.*\//, "") exit(main()) # END OF FILE qdbm-1.8.78/ruby/rbspex-ja.html0000644000175000017500000002473411426311441015315 0ustar mikiomikio Specifications of QDBM for Ruby (Japanese)

QDBM付属Ruby用API仕様書

Copyright (C) 2000-2006 Mikio Hirabayashi
Last Update: Thu, 26 Oct 2006 15:00:20 +0900

目次

  1. 概è¦
  2. インストール
  3. サンプルコード
  4. ãƒã‚°

概è¦

QDBMã«ã¯Ruby言語用ã®APIãŒã‚る。QDBMã®åŸºæœ¬APIã¨æ‹¡å¼µAPIã¨ä¸Šç´šAPIã®é–¢æ•°ç¾¤ã‚’Rubyã®ã‚¯ãƒ©ã‚¹æ©Ÿæ§‹ã‚’用ã„ã¦ã‚«ãƒ—セル化ã—ãŸã‚‚ã®ã§ã‚る。ã¾ãŸã€Rubyã®ãƒžãƒ«ãƒã‚¹ãƒ¬ãƒƒãƒ‰æ©Ÿèƒ½ã«ãŠã„ã¦ã‚¹ãƒ¬ãƒƒãƒ‰ã‚»ãƒ¼ãƒ•ã§ã‚る。

クラス `Depot' ã‹ `Curia' ã‹ `Villa' ã®ã‚³ãƒ³ã‚¹ãƒˆãƒ©ã‚¯ã‚¿ `new' を呼ã³å‡ºã—ã¦ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’é–‹ãã€ãã®æˆ»ã‚Šå€¤ã®ã‚ªãƒ–ジェクトをãƒãƒ³ãƒ‰ãƒ«ã«ã™ã‚‹ã€‚データベースを閉ã˜ã‚‹ã«ã¯ãƒ¡ã‚½ãƒƒãƒ‰ `close' を呼ã¶ã€‚ファイナライザã¯åˆ©ç”¨ã•れãªã„ãŒã€`new' ã®ã‚¤ãƒ†ãƒ¬ãƒ¼ã‚¿ã‚’用ã„ã‚‹ã“ã¨ã§ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®é–‰ã˜å¿˜ã‚Œã‚’防ãã“ã¨ãŒã§ãる。メソッド `put' ã¯ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’追加ã™ã‚‹ãŸã‚ã«ç”¨ã„る。メソッド `out' ã¯ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’削除ã™ã‚‹ãŸã‚ã«ç”¨ã„る。メソッド `get' ã¯ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’検索ã™ã‚‹ãŸã‚ã«ç”¨ã„る。ãã®ä»–ã«ã‚‚ã€C言語ã®APIã¨ã»ã¼åŒã˜æ“作を利用ã™ã‚‹ã“ã¨ãŒã§ãる。å„クラスã¯ä¾‹å¤–クラス `EANY' ãŠã‚ˆã³ãã®ã‚µãƒ–クラスを定数ã¨ã—ã¦æŒã¤ã€‚ãれらã¯å„メソッドãŒå¤±æ•—ã—ãŸéš›ã«æŠ•ã’られる。

ã“れらã®ã‚¯ãƒ©ã‚¹ã¯ `Enumerable' モジュールをMix-inã—ã¦ã„ã‚‹ã®ã§ã€`find' ã‚„ `sort' ã¨ã„ã£ãŸãƒ¡ã‚½ãƒƒãƒ‰ãŒåˆ©ç”¨ã§ãる。ã¾ãŸã€`Hash' クラスã«ä¼¼ã›ã¦ '[]=' ã‚„ '[]' ç­‰ã®ãƒ¡ã‚½ãƒƒãƒ‰ã‚’定義ã—ã¦ã„ã‚‹ã®ã§ã€æ™®é€šã®ãƒãƒƒã‚·ãƒ¥ã®ã‚ˆã†ã«åˆ©ç”¨ã™ã‚‹ã“ã¨ãŒã§ãる。

ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«æ ¼ç´ã™ã‚‹ãƒ¬ã‚³ãƒ¼ãƒ‰ã®ã‚­ãƒ¼ã¨å€¤ã¯æ–‡å­—列ã¨ã—ã¦æ‰±ã‚れるãŒã€ãƒã‚¤ãƒŠãƒªãƒ‡ãƒ¼ã‚¿ã‚’ãã®ã¾ã¾æ ¼ç´ã™ã‚‹ã“ã¨ã‚‚å¯èƒ½ã§ã‚る。ãŸã ã—ã€`Villa' ã¯ç›´åˆ—化å¯èƒ½ã‹ã¤æ¯”較å¯èƒ½ãªä»»æ„ã®ã‚ªãƒ–ジェクトを格ç´ã™ã‚‹ã“ã¨ãŒã§ãる。`Depot' ã¯ãƒ•ァイルを用ã„ã¦ãƒãƒƒã‚·ãƒ¥ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’実ç¾ã—ã€`Curia' ã¯ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã¨è¤‡æ•°ã®ãƒ•ァイルを用ã„ã¦ãƒãƒƒã‚·ãƒ¥ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’実ç¾ã—ã€`Villa' ã¯ãƒ•ァイルを用ã„ã¦B+木データベースを実ç¾ã™ã‚‹ã€‚`Depot' ã¯æœ€ã‚‚高速ã§ã‚る。`Curia' ã¯æœ€ã‚‚スケーラブルã§ã‚る。`Villa' ã¯ã‚«ãƒ¼ã‚½ãƒ«ã«ã‚ˆã£ã¦é †åºã«åŸºã¥ãå‚ç…§ã‚’å¯èƒ½ã«ã™ã‚‹ã€‚

`put' ã§æ—¢å­˜ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã®ä¸Šæ›¸ããŒã‚­ãƒ£ãƒ³ã‚»ãƒ«ã•れãŸéš›ã‚„ `get' ã§å­˜åœ¨ã—ãªã„ãƒ¬ã‚³ãƒ¼ãƒ‰ãŒæ¤œç´¢ã•れãŸéš›ã«ã¯ä¾‹å¤–ã«ã‚ˆã£ã¦æ“作ã®å¤±æ•—ãŒé€šçŸ¥ã•れるãŒã€ãれãŒé¬±é™¶ã—ã„å ´åˆã¯ `silent' フラグを真ã«ã™ã‚‹ã¨ã‚ˆã„。ãã®å ´åˆã¯å¤±æ•—ãŒæˆ»ã‚Šå€¤ã«ã‚ˆã£ã¦é€šçŸ¥ã•れる。

APIã®è©³ç´°ã«é–¢ã—ã¦ã¯ã€ã‚µãƒ–ディレクトリ `rbapidoc' ã®æ–‡æ›¸ã‚’å‚ç…§ã™ã‚‹ã“ã¨ã€‚


インストール

Rubyã®1.6.5以é™ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ãŒã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•れã€QDBM㌠`/usr/local' 以下ã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•れã¦ã„ã‚‹ã“ã¨ãŒå¿…è¦ã§ã‚る。

インストール作業ã¯ã€ã‚µãƒ–ディレクトリ `ruby' をカレントディレクトリã«ã—ã¦è¡Œã†ã€‚

cd ruby

ビルド環境を設定ã™ã‚‹ã€‚

./configure

プログラムをビルドã™ã‚‹ã€‚

make

プログラムã®è‡ªå·±è¨ºæ–­ãƒ†ã‚¹ãƒˆã‚’行ã†ã€‚

make check

プログラムをインストールã™ã‚‹ã€‚作業㯠`root' ユーザã§è¡Œã†ã€‚

make install

一連ã®ä½œæ¥­ãŒçµ‚ã‚‹ã¨ã€Rubyã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã«å¿œã˜ãŸé©å½“ãªå ´æ‰€ã« `depot.rb'ã€`mod_depot.so' ã€`curia.rb' ã€`mod_curia.so' ã€`villa.rb' ã€`mod_villa.so' ç­‰ã®ãƒ©ã‚¤ãƒ–ラリãŒã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•れã€ã‚³ãƒžãƒ³ãƒ‰ `rbdptest' 㨠`rbcrtest' 㨠`rbvltest' ㌠`/usr/local/bin' ã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•れる。

アンインストールã™ã‚‹ã«ã¯ã€`./configure' ã‚’ã—ãŸå¾Œã®çŠ¶æ…‹ã§ä»¥ä¸‹ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹ã€‚作業㯠`root' ユーザã§è¡Œã†ã€‚

make uninstall

サンプルコード

åå‰ã¨å¯¾å¿œã•ã›ã¦é›»è©±ç•ªå·ã‚’æ ¼ç´ã—ã€ãれを検索ã™ã‚‹ã‚¢ãƒ—リケーションã®ã‚µãƒ³ãƒ—ルコードを以下ã«ç¤ºã™ã€‚

require 'depot'

NAME = "mikio"
NUMBER = "000-1234-5678"
DBNAME = "book"

def main
  depot = nil
  begin

    # データベースを開ã
    depot = Depot::new(DBNAME, Depot::OWRITER | Depot::OCREAT)

    # レコードを格ç´ã™ã‚‹
    depot.put(NAME, NUMBER)

    # レコードをå–å¾—ã™ã‚‹
    printf("Name: %s\n", NAME)
    printf("Number: %s\n", depot.get(NAME))

  rescue Depot::EANY
    printf("%s\n", $!)
    return 1
  ensure

    # データベースを閉ã˜ã‚‹
    if(depot)
      begin
        depot.close()
      rescue Depot::EANY
        printf("%s\n", $!)
      end
    end

  end
  return 0
end

exit(main());

上記ã®ä¾‹ã‚’ `Hash' クラスã«ä¼¼ã›ãŸã‚¤ãƒ³ã‚¿ãƒ•ェースã¨ã‚¤ãƒ†ãƒ¬ãƒ¼ã‚¿ã‚’用ã„ã¦æ›¸ãç›´ã—ãŸä¾‹ã‚’以下ã«ç¤ºã™ã€‚

require 'depot'

NAME = "mikio"
NUMBER = "000-1234-5678"
DBNAME = "book"

def main
  begin

    # データベースを開ã„ã¦è‡ªå‹•çš„ã«é–‰ã˜ã‚‹
    Depot::new(DBNAME, Depot::OWRITER | Depot::OCREAT) do |depot|

      # レコードを格ç´ã™ã‚‹
      depot[NAME] = NUMBER

      # レコードをå–å¾—ã™ã‚‹
      printf("Name: %s\n", NAME)
      printf("Number: %s\n", depot[NAME])

    end

  rescue Depot::EANY
    printf("%s\n", $!)
    return 1
  end
  return 0
end

exit(main());

`Villa' クラスを用ã„ã¦æ–‡å­—列ã®å‰æ–¹ä¸€è‡´æ¤œç´¢ã‚’行ã†ä¾‹ã‚’以下ã«ç¤ºã™ã€‚

require 'villa'

DBNAME = "words"
PREFIX = "apple"

def main
  begin

    # データベースを開ã„ã¦è‡ªå‹•çš„ã«é–‰ã˜ã‚‹
    Villa::new(DBNAME, Villa::OWRITER | Villa::OCREAT) do |villa|

      # レコードを格ç´ã™ã‚‹
      villa.put("applet", "little application", Villa::DDUP)
      villa.put("aurora", "polar wonderwork", Villa::DDUP)
      villa.put("apple", "delicious fruit", Villa::DDUP)
      villa.put("amigo", "good friend", Villa::DDUP)
      villa.put("apple", "big city", Villa::DDUP)

      begin

        # カーソルを候補ã®å…ˆé ­ã«ç½®ã
        villa.curjump(PREFIX)

        # カーソルを走査ã™ã‚‹
        while(true)
          key = villa.curkey()
          (key.index(PREFIX) == 0) || break
          val = villa.curval()
          printf("%s: %s\n", key, val)
          villa.curnext()
        end

      rescue Villa::ENOITEM
      end

    end

  rescue Villa::EANY
    printf("%s\n", $!)
    return 1
  end
  return 0
end

exit(main());

ãƒã‚°

標準添付ライブラリ㮠`DBM' クラスã®ã‚¤ãƒ³ã‚¿ãƒ•ェースã¨å¾®å¦™ã«é•ã†ã¨ã“ã‚ãŒã‚る。

ã‚‚ã—ã‚‚Rubyãƒãƒƒã‚«ãƒ¼é”ã®æ‰‹ã«ã‹ã‹ã‚Œã°ã€ã‚ˆã‚ŠåŠ¹çŽ‡çš„ãªå®Ÿè£…ãŒãªã•れるã ã‚ã†ã€‚

インタフェースを簡潔ã«ã™ã‚‹ãŸã‚ã€Ruby用ã®Curiaã«ã¯ãƒ©ãƒ¼ã‚¸ã‚ªãƒ–ã‚¸ã‚§ã‚¯ãƒˆã‚’æ‰±ã†æ©Ÿèƒ½ã¯ãªã„。


qdbm-1.8.78/ruby/configure0000755000175000017500000032503111426320066014440 0ustar mikiomikio#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.65 for qdbm-ruby 1.0.0. # # # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, # 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, # Inc. # # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi " as_required="as_fn_return () { (exit \$1); } as_fn_success () { as_fn_return 0; } as_fn_failure () { as_fn_return 1; } as_fn_ret_success () { return 0; } as_fn_ret_failure () { return 1; } exitcode=0 as_fn_success || { exitcode=1; echo as_fn_success failed.; } as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : else exitcode=1; echo positional parameters were not saved. fi test x\$exitcode = x0 || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1" if (eval "$as_required") 2>/dev/null; then : as_have_required=yes else as_have_required=no fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. as_shell=$as_dir/$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : CONFIG_SHELL=$as_shell as_have_required=yes if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : break 2 fi fi done;; esac as_found=false done $as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : CONFIG_SHELL=$SHELL as_have_required=yes fi; } IFS=$as_save_IFS if test "x$CONFIG_SHELL" != x; then : # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV export CONFIG_SHELL exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"} fi if test x$as_have_required = xno; then : $as_echo "$0: This script requires a shell more modern than all" $as_echo "$0: the shells that I found on your system." if test x${ZSH_VERSION+set} = xset ; then $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" $as_echo "$0: be upgraded to zsh 4.3.4 or later." else $as_echo "$0: Please tell bug-autoconf@gnu.org about your system, $0: including any error possibly output before this $0: message. Then install a modern shell, or manually run $0: the script under such a shell if you do have one." fi exit 1 fi fi fi SHELL=${CONFIG_SHELL-/bin/sh} export SHELL # Unset more variables known to interfere with behavior of common tools. CLICOLOR_FORCE= GREP_OPTIONS= unset CLICOLOR_FORCE GREP_OPTIONS ## --------------------- ## ## M4sh Shell Functions. ## ## --------------------- ## # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error "cannot create directory $as_dir" } # as_fn_mkdir_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith # as_fn_error ERROR [LINENO LOG_FD] # --------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with status $?, using 1 if that was 0. as_fn_error () { as_status=$?; test $as_status -eq 0 && as_status=1 if test "$3"; then as_lineno=${as_lineno-"$2"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $1" >&$3 fi $as_echo "$as_me: error: $1" >&2 as_fn_exit $as_status } # as_fn_error if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits as_lineno_1=$LINENO as_lineno_1a=$LINENO as_lineno_2=$LINENO as_lineno_2a=$LINENO eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -p'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -p' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -p' fi else as_ln_s='cp -p' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi if test -x / >/dev/null 2>&1; then as_test_x='test -x' else if ls -dL / >/dev/null 2>&1; then as_ls_L_option=L else as_ls_L_option= fi as_test_x=' eval sh -c '\'' if test -d "$1"; then test -d "$1/."; else case $1 in #( -*)set "./$1";; esac; case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( ???[sx]*):;;*)false;;esac;fi '\'' sh ' fi as_executable_p=$as_test_x # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME='qdbm-ruby' PACKAGE_TARNAME='qdbm-ruby' PACKAGE_VERSION='1.0.0' PACKAGE_STRING='qdbm-ruby 1.0.0' PACKAGE_BUGREPORT='' PACKAGE_URL='' ac_subst_vars='LTLIBOBJS LIBOBJS OBJEXT EXEEXT ac_ct_CC CPPFLAGS LDFLAGS CFLAGS CC target_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_URL PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL' ac_subst_files='' ac_user_opts=' enable_option_checking ' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS' # Initialize some variables set by options. ac_init_help= ac_init_version=false ac_unrecognized_opts= ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) as_fn_error "unrecognized option: \`$ac_option' Try \`$0 --help' for more information." ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) as_fn_error "invalid variable name: \`$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` as_fn_error "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) as_fn_error "unrecognized options: $ac_unrecognized_opts" ;; *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi # Check all directory arguments for consistency. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir do eval ac_val=\$$ac_var # Remove trailing slashes. case $ac_val in */ ) ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` eval $ac_var=\$ac_val;; esac # Be sure to have absolute directory names. case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac as_fn_error "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe $as_echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. If a cross compiler is detected then cross compile mode will be used." >&2 elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || as_fn_error "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || as_fn_error "pwd does not report name of working directory" # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." as_fn_error "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures qdbm-ruby 1.0.0 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/qdbm-ruby] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of qdbm-ruby 1.0.0:";; esac cat <<\_ACEOF Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to the package provider. _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for guested configure. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF qdbm-ruby configure 1.0.0 generated by GNU Autoconf 2.65 Copyright (C) 2009 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi ## ------------------------ ## ## Autoconf initialization. ## ## ------------------------ ## # ac_fn_c_try_compile LINENO # -------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} as_fn_set_status $ac_retval } # ac_fn_c_try_compile # ac_fn_c_try_link LINENO # ----------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} as_fn_set_status $ac_retval } # ac_fn_c_try_link cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by qdbm-ruby $as_me 1.0.0, which was generated by GNU Autoconf 2.65. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. $as_echo "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) as_fn_append ac_configure_args1 " '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done { ac_configure_args0=; unset ac_configure_args0;} { ac_configure_args1=; unset ac_configure_args1;} # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo cat <<\_ASBOX ## ---------------- ## ## Cache variables. ## ## ---------------- ## _ASBOX echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo cat <<\_ASBOX ## ----------------- ## ## Output variables. ## ## ----------------- ## _ASBOX echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then cat <<\_ASBOX ## ------------------- ## ## File substitutions. ## ## ------------------- ## _ASBOX echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then cat <<\_ASBOX ## ----------- ## ## confdefs.h. ## ## ----------- ## _ASBOX echo cat confdefs.h echo fi test "$ac_signal" != 0 && $as_echo "$as_me: caught signal $ac_signal" $as_echo "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h $as_echo "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_URL "$PACKAGE_URL" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. ac_site_file1=NONE ac_site_file2=NONE if test -n "$CONFIG_SITE"; then ac_site_file1=$CONFIG_SITE elif test "x$prefix" != xNONE; then ac_site_file1=$prefix/share/config.site ac_site_file2=$prefix/etc/config.site else ac_site_file1=$ac_default_prefix/share/config.site ac_site_file2=$ac_default_prefix/etc/config.site fi for ac_site_file in "$ac_site_file1" "$ac_site_file2" do test "x$ac_site_file" = xNONE && continue if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 $as_echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 $as_echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 $as_echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then # differences in whitespace do not lead to failure. ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 $as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 $as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 $as_echo "$as_me: former value: \`$ac_old_val'" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 $as_echo "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 $as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} as_fn_error "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## ## -------------------- ## ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu # Building paths pathtmp="$PATH" PATH="$HOME/bin:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin" PATH="$PATH:/usr/ccs/bin:/usr/ucb:/usr/xpg4/bin:/usr/xpg6/bin:$pathtmp" LIBRARY_PATH="$HOME/lib:/usr/local/lib:$LIBRARY_PATH" LD_LIBRARY_PATH="$HOME/lib:/usr/local/lib:$LD_LIBRARY_PATH" CPATH="$HOME/include:/usr/local/include:$CPATH" export PATH LIBRARY_PATH LD_LIBRARY_PATH CPATH # Setting the default prefix if test "$prefix" = NONE then prefix=`ruby -rrbconfig -e 'puts(Config::CONFIG.fetch("prefix"))'` fi # Duplication of QDBM for Ruby ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_CC+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_ac_ct_CC+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_CC+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_CC+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_CC+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_ac_ct_CC+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error "no acceptable C compiler found in \$PATH See \`config.log' for more details." "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 $as_echo_n "checking whether the C compiler works... " >&6; } ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # The possible output files: ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { { ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link_default") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an `-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else ac_file='' fi if test -z "$ac_file"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { as_fn_set_status 77 as_fn_error "C compiler cannot create executables See \`config.log' for more details." "$LINENO" 5; }; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 $as_echo_n "checking for C compiler default output file name... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 $as_echo "$ac_file" >&6; } ac_exeext=$ac_cv_exeext rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 $as_echo_n "checking for suffix of executables... " >&6; } if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error "cannot compute suffix of executables: cannot compile and link See \`config.log' for more details." "$LINENO" 5; } fi rm -f conftest conftest$ac_cv_exeext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 $as_echo "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { FILE *f = fopen ("conftest.out", "w"); return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF ac_clean_files="$ac_clean_files conftest.out" # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 $as_echo_n "checking whether we are cross compiling... " >&6; } if test "$cross_compiling" != yes; then { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if { ac_try='./conftest$ac_cv_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error "cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details." "$LINENO" 5; } fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 $as_echo "$cross_compiling" >&6; } rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 $as_echo_n "checking for suffix of object files... " >&6; } if test "${ac_cv_objext+set}" = set; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error "cannot compute suffix of object files: cannot compile See \`config.log' for more details." "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 $as_echo "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if test "${ac_cv_c_compiler_gnu+set}" = set; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if test "${ac_cv_prog_cc_g+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if test "${ac_cv_prog_cc_c89+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lqdbm" >&5 $as_echo_n "checking for main in -lqdbm... " >&6; } if test "${ac_cv_lib_qdbm_main+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lqdbm $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_qdbm_main=yes else ac_cv_lib_qdbm_main=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_qdbm_main" >&5 $as_echo "$ac_cv_lib_qdbm_main" >&6; } if test "x$ac_cv_lib_qdbm_main" = x""yes; then : true else printf 'checking whether /usr/local/lib/libqdbm.* is... ' if ls /usr/local/lib/libqdbm.* > /dev/null 2>&1 then printf 'yes\n' else printf 'no\n' printf '#================================================================\n' 1>&2 printf '# WARNING: Install QDBM libraries before installation.\n' 1>&2 printf '#================================================================\n' 1>&2 fi fi # Targets ac_config_files="$ac_config_files Makefile" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then test "x$cache_file" != "x/dev/null" && { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} cat confcache >$cache_file else { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' # Transform confdefs.h into DEFS. # Protect against shell expansion while executing Makefile rules. # Protect against Makefile macro expansion. # # If the first sed substitution is executed (which looks for macros that # take arguments), then branch to the quote section. Otherwise, # look for a macro that doesn't take arguments. ac_script=' :mline /\\$/{ N s,\\\n,, b mline } t clear :clear s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g t quote s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g t quote b any :quote s/[ `~#$^&*(){}\\|;'\''"<>?]/\\&/g s/\[/\\&/g s/\]/\\&/g s/\$/$$/g H :any ${ g s/^\n// s/\n/ /g p } ' DEFS=`sed -n "$ac_script" confdefs.h` ac_libobjs= ac_ltlibobjs= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`$as_echo "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs : ${CONFIG_STATUS=./config.status} ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 $as_echo "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # as_fn_error ERROR [LINENO LOG_FD] # --------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with status $?, using 1 if that was 0. as_fn_error () { as_status=$?; test $as_status -eq 0 && as_status=1 if test "$3"; then as_lineno=${as_lineno-"$2"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $1" >&$3 fi $as_echo "$as_me: error: $1" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -p'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -p' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -p' fi else as_ln_s='cp -p' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi if test -x / >/dev/null 2>&1; then as_test_x='test -x' else if ls -dL / >/dev/null 2>&1; then as_ls_L_option=L else as_ls_L_option= fi as_test_x=' eval sh -c '\'' if test -d "$1"; then test -d "$1/."; else case $1 in #( -*)set "./$1";; esac; case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( ???[sx]*):;;*)false;;esac;fi '\'' sh ' fi as_executable_p=$as_test_x # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 ## ----------------------------------- ## ## Main body of $CONFIG_STATUS script. ## ## ----------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by qdbm-ruby $as_me 1.0.0, which was generated by GNU Autoconf 2.65. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ \`$as_me' instantiates files and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit --config print configuration, then exit -q, --quiet, --silent do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE Configuration files: $config_files Report bugs to the package provider." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ qdbm-ruby config.status 1.0.0 configured by $0, generated by GNU Autoconf 2.65, with options \\"\$ac_cs_config\\" Copyright (C) 2009 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) $as_echo "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) $as_echo "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --he | --h | --help | --hel | -h ) $as_echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) as_fn_error "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX $as_echo "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; *) as_fn_error "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= trap 'exit_status=$? { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error "cannot create a temporary directory in ." "$LINENO" 5 # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with `./config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=`echo X | tr X '\015'` # On cygwin, bash can eat \r inside `` if the user requested igncr. # But we know of no other shell where ac_cr would be empty at this # point, so we can use a bashism as a fallback. if test "x$ac_cr" = x; then eval ac_cr=\$\'\\r\' fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_num=`echo "$ac_subst_vars" | grep -c '$'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>"\$tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\)..*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\)..*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' >$CONFIG_STATUS || ac_write_fail=1 rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$tmp/subs1.awk" > "$tmp/subs.awk" \ || as_fn_error "could not setup config files machinery" "$LINENO" 5 _ACEOF # VPATH may cause trouble with some makes, so we remove $(srcdir), # ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=/{ s/:*\$(srcdir):*/:/ s/:*\${srcdir}:*/:/ s/:*@srcdir@:*/:/ s/^\([^=]*=[ ]*\):*/\1/ s/:*$// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" eval set X " :F $CONFIG_FILES " shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) as_fn_error "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || as_fn_error "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 $as_echo "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`$as_echo "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$tmp/stdin" \ || as_fn_error "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 $as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$tmp/subs.awk" >$tmp/out \ || as_fn_error "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } && { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined." >&5 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined." >&2;} rm -f "$tmp/stdin" case $ac_file in -) cat "$tmp/out" && rm -f "$tmp/out";; *) rm -f "$ac_file" && mv "$tmp/out" "$ac_file";; esac \ || as_fn_error "could not create $ac_file" "$LINENO" 5 ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || as_fn_error "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit $? fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi # END OF FILE qdbm-1.8.78/vista.h0000644000175000017500000001073210573416530013052 0ustar mikiomikio/************************************************************************************************* * The extended advanced API of QDBM * Copyright (C) 2000-2007 Mikio Hirabayashi * This file is part of QDBM, Quick Database Manager. * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU * Lesser General Public License as published by the Free Software Foundation; either version * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * You should have received a copy of the GNU Lesser General Public License along with QDBM; if * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. *************************************************************************************************/ #ifndef _VISTA_H /* duplication check */ #define _VISTA_H #if defined(__cplusplus) /* export for C++ */ extern "C" { #endif /************************************************************************************************* * macros to borrow symbols from Villa *************************************************************************************************/ #include #include #include #include #define VLREC VSTREC #define VLIDX VSTIDX #define VLLEAF VSTLEAF #define VLNODE VSTNODE #define VLCFUNC VSTCFUNC #define VL_CMPLEX VST_CMPLEX #define VL_CMPINT VST_CMPINT #define VL_CMPNUM VST_CMPNUM #define VL_CMPDEC VST_CMPDEC #define VILLA VISTA #define VL_OREADER VST_OREADER #define VL_OWRITER VST_OWRITER #define VL_OCREAT VST_OCREAT #define VL_OTRUNC VST_OTRUNC #define VL_ONOLCK VST_ONOLCK #define VL_OLCKNB VST_OLCKNB #define VL_OZCOMP VST_OZCOMP #define VL_DOVER VST_DOVER #define VL_DKEEP VST_DKEEP #define VL_DCAT VST_DCAT #define VL_DDUP VST_DDUP #define VL_JFORWARD VST_JFORWARD #define VL_JBACKWARD VST_JBACKWARD #define vlopen vstopen #define vlclose vstclose #define vlput vstput #define vlout vstout #define vlget vstget #define vlvsiz vstvsiz #define vlvnum vstvnum #define vlputlist vstputlist #define vloutlist vstoutlist #define vlgetlist vstgetlist #define vlgetcat vstgetcat #define vlcurfirst vstcurfirst #define vlcurlast vstcurlast #define vlcurprev vstcurprev #define vlcurnext vstcurnext #define vlcurjump vstcurjump #define vlcurkey vstcurkey #define vlcurval vstcurval #define vlcurput vstcurput #define vlcurout vstcurout #define vlsettuning vstsettuning #define vlsync vstsync #define vloptimize vstoptimize #define vlname vstname #define vlfsiz vstfsiz #define vllnum vstlnum #define vlnnum vstnnum #define vlrnum vstrnum #define vlwritable vstwritable #define vlfatalerror vstfatalerror #define vlinode vstinode #define vlmtime vstmtime #define vltranbegin vsttranbegin #define vltrancommit vsttrancommit #define vltranabort vsttranabort #define vlremove vstremove #define vlrepair vstrepair #define vlexportdb vstexportdb #define vlimportdb vstimportdb #define vlcrdnumptr vstcrdnumptr #define vlmemsync vstmemsync #define vlmemflush vstmemflush #define vlgetcache vstgetcache #define vlcurkeycache vstcurkeycache #define vlcurvalcache vstcurvalcache #define vlmulcuropen vstmulcuropen #define vlmulcurclose vstmulcurclose #define vlmulcurfirst vstmulcurfirst #define vlmulcurlast vstmulcurlast #define vlmulcurprev vstmulcurprev #define vlmulcurnext vstmulcurnext #define vlmulcurjump vstmulcurjump #define vlmulcurkey vstmulcurkey #define vlmulcurval vstmulcurval #define vlmulcurkeycache vstmulcurkeycache #define vlmulcurvalcache vstmulcurvalcache #define vlsetfbpsiz vstsetfbpsiz #define vlgetflags vstgetflags #define vlsetflags vstsetflags #if !defined(_VISTA_C) #include #endif #if defined(__cplusplus) /* export for C++ */ } #endif #endif /* duplication check */ /* END OF FILE */ qdbm-1.8.78/cabin.c0000644000175000017500000027110110651144510012763 0ustar mikiomikio/************************************************************************************************* * Implementation of Cabin * Copyright (C) 2000-2007 Mikio Hirabayashi * This file is part of QDBM, Quick Database Manager. * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU * Lesser General Public License as published by the Free Software Foundation; either version * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * You should have received a copy of the GNU Lesser General Public License along with QDBM; if * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. *************************************************************************************************/ #define QDBM_INTERNAL 1 #include "cabin.h" #include "myconf.h" #define CB_GCUNIT 64 /* allocation unit size of a buffer in gc */ #define CB_SPBUFSIZ 32 /* size of a buffer for sprintf */ #define CB_SPMAXWIDTH 128 /* max width of a column for sprintf */ #define CB_MAPPBNUM 251 /* bucket size of a petit map handle */ #define CB_MAPCSUNIT 52 /* small allocation unit size of map concatenation */ #define CB_MAPCBUNIT 252 /* big allocation unit size of map concatenation */ #define CB_MSGBUFSIZ 256 /* size of a buffer for log message */ #define CB_IOBUFSIZ 8192 /* size of an I/O buffer */ #define CB_FILEMODE 00644 /* permission of a creating file */ #define CB_NUMBUFSIZ 32 /* size of a buffer for a number */ #define CB_ENCBUFSIZ 32 /* size of a buffer for encoding name */ #define CB_DATEBUFSIZ 64 /* size of a buffer for date expression */ #define CB_VNUMBUFSIZ 8 /* size of a buffer for variable length number */ /* set a buffer for a variable length number */ #define CB_SETVNUMBUF(CB_len, CB_buf, CB_num) \ do { \ int _CB_num; \ _CB_num = (CB_num); \ if(_CB_num == 0){ \ ((signed char *)(CB_buf))[0] = 0; \ (CB_len) = 1; \ } else { \ (CB_len) = 0; \ while(_CB_num > 0){ \ int _CB_rem = _CB_num & 0x7f; \ _CB_num >>= 7; \ if(_CB_num > 0){ \ ((signed char *)(CB_buf))[(CB_len)] = -_CB_rem - 1; \ } else { \ ((signed char *)(CB_buf))[(CB_len)] = _CB_rem; \ } \ (CB_len)++; \ } \ } \ } while(FALSE) /* read a variable length buffer */ #define CB_READVNUMBUF(CB_buf, CB_size, CB_num, CB_step) \ do { \ int _CB_i, _CB_base; \ CB_num = 0; \ _CB_base = 1; \ if((size) < 2){ \ CB_num = ((signed char *)(CB_buf))[0]; \ (CB_step) = 1; \ } else { \ for(_CB_i = 0; _CB_i < (size); _CB_i++){ \ if(((signed char *)(CB_buf))[_CB_i] >= 0){ \ CB_num += ((signed char *)(CB_buf))[_CB_i] * _CB_base; \ break; \ } \ CB_num += _CB_base * (((signed char *)(CB_buf))[_CB_i] + 1) * -1; \ _CB_base *= 128; \ } \ (CB_step) = _CB_i + 1; \ } \ } while(FALSE) /* get the first hash value */ #define CB_FIRSTHASH(CB_res, CB_kbuf, CB_ksiz) \ do { \ const unsigned char *_CB_p; \ int _CB_ksiz; \ _CB_p = (const unsigned char *)(CB_kbuf); \ _CB_ksiz = CB_ksiz; \ for((CB_res) = 19780211; _CB_ksiz--;){ \ (CB_res) = (CB_res) * 37 + *(_CB_p)++; \ } \ (CB_res) &= INT_MAX; \ } while(FALSE) /* get the second hash value */ #define CB_SECONDHASH(CB_res, CB_kbuf, CB_ksiz) \ do { \ const unsigned char *_CB_p; \ int _CB_ksiz; \ _CB_p = (const unsigned char *)(CB_kbuf) + CB_ksiz - 1; \ _CB_ksiz = CB_ksiz; \ for((CB_res) = 0x13579bdf; _CB_ksiz--;){ \ (CB_res) = (CB_res) * 31 + *(_CB_p)--; \ } \ (CB_res) &= INT_MAX; \ } while(FALSE) /* private function prototypes */ static void cbggchandler(void); static void cbggckeeper(void *ptr, void (*func)(void *)); static void cbqsortsub(char *bp, int nmemb, int size, char *pswap, char *vswap, int(*compar)(const void *, const void *)); static int cblistelemcmp(const void *a, const void *b); static int cbkeycmp(const char *abuf, int asiz, const char *bbuf, int bsiz); /************************************************************************************************* * public objects *************************************************************************************************/ /* Call back function for handling a fatal error. */ void (*cbfatalfunc)(const char *message) = NULL; /* Allocate a region on memory. */ void *cbmalloc(size_t size){ char *p; assert(size > 0 && size < INT_MAX); if(!(p = malloc(size))) cbmyfatal("out of memory"); return p; } /* Re-allocate a region on memory. */ void *cbrealloc(void *ptr, size_t size){ char *p; assert(size > 0); if(!(p = realloc(ptr, size))) cbmyfatal("out of memory"); return p; } /* Duplicate a region on memory. */ char *cbmemdup(const char *ptr, int size){ char *p; assert(ptr); if(size < 0) size = strlen(ptr); CB_MALLOC(p, size + 1); memcpy(p, ptr, size); p[size] = '\0'; return p; } /* Free a region on memory. */ void cbfree(void *ptr){ free(ptr); } /* Register the pointer or handle of an object to the global garbage collector. */ void cbglobalgc(void *ptr, void (*func)(void *)){ assert(ptr && func); cbggckeeper(ptr, func); } /* Exercise the global garbage collector explicitly. */ void cbggcsweep(void){ cbggckeeper(NULL, NULL); } /* Check availability of allocation of the virtual memory. */ int cbvmemavail(size_t size){ assert(size >= 0); return _qdbm_vmemavail(size); } /* Sort an array using insert sort. */ void cbisort(void *base, int nmemb, int size, int(*compar)(const void *, const void *)){ char *bp, *swap; int i, j; assert(base && nmemb >= 0 && size > 0 && compar); bp = (char *)base; CB_MALLOC(swap, size); for(i = 1; i < nmemb; i++){ if(compar(bp + (i - 1) * size, bp + i * size) > 0){ memcpy(swap, bp + i * size, size); for(j = i; j > 0; j--){ if(compar(bp + (j - 1) * size, swap) < 0) break; memcpy(bp + j * size, bp + (j - 1) * size, size); } memcpy(bp + j * size, swap, size); } } free(swap); } /* Sort an array using shell sort. */ void cbssort(void *base, int nmemb, int size, int(*compar)(const void *, const void *)){ char *bp, *swap; int step, bottom, i, j; assert(base && nmemb >= 0 && size > 0 && compar); bp = (char *)base; CB_MALLOC(swap, size); for(step = (nmemb - 1) / 3; step >= 0; step = (step - 1) / 3){ if(step < 5) step = 1; for(bottom = 0; bottom < step; bottom++){ for(i = bottom + step; i < nmemb; i += step){ if(compar(bp + (i - step) * size, bp + i * size) > 0){ memcpy(swap, bp + i * size, size); for(j = i; j > step - 1; j -= step){ if(compar(bp + (j - step) * size, swap) < 0) break; memcpy(bp + j * size, bp + (j - step) * size, size); } memcpy(bp + j * size, swap, size); } } } if(step < 2) break; } free(swap); } /* Sort an array using heap sort. */ void cbhsort(void *base, int nmemb, int size, int(*compar)(const void *, const void *)){ char *bp, *swap; int top, bottom, mybot, i; assert(base && nmemb >= 0 && size > 0 && compar); bp = (char *)base; nmemb--; bottom = nmemb / 2 + 1; top = nmemb; CB_MALLOC(swap, size); while(bottom > 0){ bottom--; mybot = bottom; i = 2 * mybot; while(i <= top) { if(i < top && compar(bp + (i + 1) * size, bp + i * size) > 0) i++; if(compar(bp + mybot * size, bp + i * size) >= 0) break; memcpy(swap, bp + mybot * size, size); memcpy(bp + mybot * size, bp + i * size, size); memcpy(bp + i * size, swap, size); mybot = i; i = 2 * mybot; } } while(top > 0){ memcpy(swap, bp, size); memcpy(bp, bp + top * size, size); memcpy(bp + top * size, swap, size); top--; mybot = bottom; i = 2 * mybot; while(i <= top){ if(i < top && compar(bp + (i + 1) * size, bp + i * size) > 0) i++; if(compar(bp + mybot * size, bp + i * size) >= 0) break; memcpy(swap, bp + mybot * size, size); memcpy(bp + mybot * size, bp + i * size, size); memcpy(bp + i * size, swap, size); mybot = i; i = 2 * mybot; } } free(swap); } /* Sort an array using quick sort. */ void cbqsort(void *base, int nmemb, int size, int(*compar)(const void *, const void *)){ char *pswap, *vswap; assert(base && nmemb >= 0 && size > 0 && compar); CB_MALLOC(pswap, size); CB_MALLOC(vswap, size); cbqsortsub(base, nmemb, size, pswap, vswap, compar); free(vswap); free(pswap); } /* Compare two strings with case insensitive evaluation. */ int cbstricmp(const char *astr, const char *bstr){ int ac, bc; assert(astr && bstr); while(*astr != '\0'){ if(*bstr == '\0') return 1; ac = (*astr >= 'A' && *astr <= 'Z') ? *astr + ('a' - 'A') : *(unsigned char *)astr; bc = (*bstr >= 'A' && *bstr <= 'Z') ? *bstr + ('a' - 'A') : *(unsigned char *)bstr; if(ac != bc) return ac - bc; astr++; bstr++; } return *bstr == '\0' ? 0 : -1; } /* Check whether a string begins with a key. */ int cbstrfwmatch(const char *str, const char *key){ assert(str && key); while(*key != '\0'){ if(*str != *key || *str == '\0') return FALSE; key++; str++; } return TRUE; } /* Check whether a string begins with a key, with case insensitive evaluation. */ int cbstrfwimatch(const char *str, const char *key){ int sc, kc; assert(str && key); while(*key != '\0'){ if(*str == '\0') return FALSE; sc = *str; if(sc >= 'A' && sc <= 'Z') sc += 'a' - 'A'; kc = *key; if(kc >= 'A' && kc <= 'Z') kc += 'a' - 'A'; if(sc != kc) return FALSE; key++; str++; } return TRUE; } /* Check whether a string ends with a key. */ int cbstrbwmatch(const char *str, const char *key){ int slen, klen, i; assert(str && key); slen = strlen(str); klen = strlen(key); for(i = 1; i <= klen; i++){ if(i > slen || str[slen-i] != key[klen-i]) return FALSE; } return TRUE; } /* Check whether a string ends with a key, with case insensitive evaluation. */ int cbstrbwimatch(const char *str, const char *key){ int slen, klen, i, sc, kc; assert(str && key); slen = strlen(str); klen = strlen(key); for(i = 1; i <= klen; i++){ if(i > slen) return FALSE; sc = str[slen-i]; if(sc >= 'A' && sc <= 'Z') sc += 'a' - 'A'; kc = key[klen-i]; if(kc >= 'A' && kc <= 'Z') kc += 'a' - 'A'; if(sc != kc) return FALSE; } return TRUE; } /* Locate a substring in a string using KMP method. */ char *cbstrstrkmp(const char *haystack, const char *needle){ int i, j, hlen, nlen; signed char tbl[0x100]; assert(haystack && needle); nlen = strlen(needle); if(nlen >= 0x100) return strstr(haystack, needle); tbl[0] = -1; i = 0; j = -1; while(i < nlen){ while((j >= 0) && (needle[i] != needle[j])){ j = tbl[j]; } i++; j++; tbl[i] = j; } hlen = strlen(haystack); i = 0; j = 0; while(i < hlen && j < nlen){ while((j >= 0) && (haystack[i] != needle[j])){ j = tbl[j]; } i++; j++; } if(j == nlen) return (char *)(haystack + i - nlen); return NULL; } /* Locate a substring in a string using BM method. */ char *cbstrstrbm(const char *haystack, const char *needle){ const unsigned char *rp; const char *ep; unsigned char tbl[0x100]; int i, j, nlen, len, idx; assert(haystack && needle); nlen = strlen(needle); if(nlen < 3 || nlen >= 0x100) return strstr(haystack, needle); for(i = 0; i < 0x100; i++){ tbl[i] = nlen; } len = nlen; rp = (const unsigned char *)needle; while(len > 0){ tbl[*rp++] = --len; } nlen--; ep = haystack + strlen(haystack) - nlen; while(haystack < ep){ for(i = nlen; haystack[i] == needle[i]; i--){ if(i == 0) return (char *)haystack; } idx = ((unsigned char *)haystack)[i]; j = tbl[idx] - nlen + i; haystack += j > 0 ? j : 2; } return NULL; } /* Convert the letters of a string to upper case. */ char *cbstrtoupper(char *str){ int i; assert(str); for(i = 0; str[i] != '\0'; i++){ if(str[i] >= 'a' && str[i] <= 'z') str[i] -= 'a' - 'A'; } return str; } /* Convert the letters of a string to lower case. */ char *cbstrtolower(char *str){ int i; assert(str); for(i = 0; str[i] != '\0'; i++){ if(str[i] >= 'A' && str[i] <= 'Z') str[i] += 'a' - 'A'; } return str; } /* Cut space characters at head or tail of a string. */ char *cbstrtrim(char *str){ char *wp; int i, head; assert(str); wp = str; head = TRUE; for(i = 0; str[i] != '\0'; i++){ if((str[i] >= 0x07 && str[i] <= 0x0d) || str[i] == 0x20){ if(!head) *(wp++) = str[i]; } else { *(wp++) = str[i]; head = FALSE; } } *wp = '\0'; while(wp > str && ((wp[-1] >= 0x07 && wp[-1] <= 0x0d) || wp[-1] == 0x20)){ *(--wp) = '\0'; } return str; } /* Squeeze space characters in a string and trim it. */ char *cbstrsqzspc(char *str){ char *wp; int i, spc; assert(str); wp = str; spc = TRUE; for(i = 0; str[i] != '\0'; i++){ if(str[i] > 0 && str[i] <= ' '){ if(!spc) *(wp++) = str[i]; spc = TRUE; } else { *(wp++) = str[i]; spc = FALSE; } } *wp = '\0'; for(wp--; wp >= str; wp--){ if(*wp > 0 && *wp <= ' '){ *wp = '\0'; } else { break; } } return str; } /* Count the number of characters in a string of UTF-8. */ int cbstrcountutf(const char *str){ const unsigned char *rp; int cnt; assert(str); rp = (unsigned char *)str; cnt = 0; while(*rp != '\0'){ if((*rp & 0x80) == 0x00 || (*rp & 0xe0) == 0xc0 || (*rp & 0xf0) == 0xe0 || (*rp & 0xf8) == 0xf0) cnt++; rp++; } return cnt; } /* Cut a string of UTF-8 at the specified number of characters. */ char *cbstrcututf(char *str, int num){ unsigned char *wp; int cnt; assert(str && num >= 0); wp = (unsigned char *)str; cnt = 0; while(*wp != '\0'){ if((*wp & 0x80) == 0x00 || (*wp & 0xe0) == 0xc0 || (*wp & 0xf0) == 0xe0 || (*wp & 0xf8) == 0xf0){ cnt++; if(cnt > num){ *wp = '\0'; break; } } wp++; } return str; } /* Get a datum handle. */ CBDATUM *cbdatumopen(const char *ptr, int size){ CBDATUM *datum; CB_MALLOC(datum, sizeof(*datum)); CB_MALLOC(datum->dptr, CB_DATUMUNIT); datum->dptr[0] = '\0'; datum->dsize = 0; datum->asize = CB_DATUMUNIT; if(ptr) CB_DATUMCAT(datum, ptr, (size >= 0 ? size : strlen(ptr))); return datum; } /* Copy a datum. */ CBDATUM *cbdatumdup(const CBDATUM *datum){ assert(datum); return cbdatumopen(datum->dptr, datum->dsize); } /* Free a datum handle. */ void cbdatumclose(CBDATUM *datum){ assert(datum); free(datum->dptr); free(datum); } /* Concatenate a datum and a region. */ void cbdatumcat(CBDATUM *datum, const char *ptr, int size){ assert(datum && ptr); if(size < 0) size = strlen(ptr); if(datum->dsize + size >= datum->asize){ datum->asize = datum->asize * 2 + size + 1; CB_REALLOC(datum->dptr, datum->asize); } memcpy(datum->dptr + datum->dsize, ptr, size); datum->dsize += size; datum->dptr[datum->dsize] = '\0'; } /* Get the pointer of the region of a datum. */ const char *cbdatumptr(const CBDATUM *datum){ assert(datum); return datum->dptr; } /* Get the size of the region of a datum. */ int cbdatumsize(const CBDATUM *datum){ assert(datum); return datum->dsize; } /* Set the size of the region of a datum. */ void cbdatumsetsize(CBDATUM *datum, int size){ assert(datum && size >= 0); if(size <= datum->dsize){ datum->dsize = size; datum->dptr[size] = '\0'; } else { if(size >= datum->asize){ datum->asize = datum->asize * 2 + size + 1; CB_REALLOC(datum->dptr, datum->asize); } memset(datum->dptr + datum->dsize, 0, (size - datum->dsize) + 1); datum->dsize = size; } } /* Perform formatted output into a datum. */ void cbdatumprintf(CBDATUM *datum, const char *format, ...){ va_list ap; char *tmp, cbuf[CB_NUMBUFSIZ], tbuf[CB_NUMBUFSIZ*2]; unsigned char c; int cblen, tlen; assert(datum && format); va_start(ap, format); while(*format != '\0'){ if(*format == '%'){ cbuf[0] = '%'; cblen = 1; format++; while(strchr("0123456789 .+-", *format) && *format != '\0' && cblen < CB_NUMBUFSIZ - 1){ cbuf[cblen++] = *format; format++; } cbuf[cblen++] = *format; cbuf[cblen] = '\0'; switch(*format){ case 's': tmp = va_arg(ap, char *); if(!tmp) tmp = "(null)"; cbdatumcat(datum, tmp, -1); break; case 'd': tlen = sprintf(tbuf, cbuf, va_arg(ap, int)); cbdatumcat(datum, tbuf, tlen); break; case 'o': case 'u': case 'x': case 'X': case 'c': tlen = sprintf(tbuf, cbuf, va_arg(ap, unsigned int)); cbdatumcat(datum, tbuf, tlen); break; case 'e': case 'E': case 'f': case 'g': case 'G': tlen = sprintf(tbuf, cbuf, va_arg(ap, double)); cbdatumcat(datum, tbuf, tlen); break; case '@': tmp = va_arg(ap, char *); if(!tmp) tmp = "(null)"; while(*tmp){ switch(*tmp){ case '&': cbdatumcat(datum, "&", 5); break; case '<': cbdatumcat(datum, "<", 4); break; case '>': cbdatumcat(datum, ">", 4); break; case '"': cbdatumcat(datum, """, 6); break; default: if(!((*tmp >= 0 && *tmp <= 0x8) || (*tmp >= 0x0e && *tmp <= 0x1f))) cbdatumcat(datum, tmp, 1); break; } tmp++; } break; case '?': tmp = va_arg(ap, char *); if(!tmp) tmp = "(null)"; while(*tmp){ c = *(unsigned char *)tmp; if((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || (c != '\0' && strchr("_-.", c))){ cbdatumcat(datum, tmp, 1); } else { tlen = sprintf(tbuf, "%%%02X", c); cbdatumcat(datum, tbuf, tlen); } tmp++; } break; case ':': tmp = va_arg(ap, char *); if(!tmp) tmp = ""; tmp = cbmimeencode(tmp, "UTF-8", TRUE); cbdatumcat(datum, tmp, -1); free(tmp); break; case '%': cbdatumcat(datum, "%", 1); break; } } else { cbdatumcat(datum, format, 1); } format++; } va_end(ap); } /* Convert a datum to an allocated region. */ char *cbdatumtomalloc(CBDATUM *datum, int *sp){ char *ptr; assert(datum); ptr = datum->dptr; if(sp) *sp = datum->dsize; free(datum); return ptr; } /* Get a list handle. */ CBLIST *cblistopen(void){ CBLIST *list; CB_MALLOC(list, sizeof(*list)); list->anum = CB_LISTUNIT; CB_MALLOC(list->array, sizeof(list->array[0]) * list->anum); list->start = 0; list->num = 0; return list; } /* Copy a list. */ CBLIST *cblistdup(const CBLIST *list){ CBLIST *newlist; int i, size; const char *val; assert(list); CB_LISTOPEN2(newlist, CB_LISTNUM(list)); for(i = 0; i < CB_LISTNUM(list); i++){ val = CB_LISTVAL2(list, i, size); CB_LISTPUSH(newlist, val, size); } return newlist; } /* Close a list handle. */ void cblistclose(CBLIST *list){ int i, end; assert(list); end = list->start + list->num; for(i = list->start; i < end; i++){ free(list->array[i].dptr); } free(list->array); free(list); } /* Get the number of elements of a list. */ int cblistnum(const CBLIST *list){ assert(list); return list->num; } /* Get the pointer to the region of an element. */ const char *cblistval(const CBLIST *list, int index, int *sp){ assert(list && index >= 0); if(index >= list->num) return NULL; index += list->start; if(sp) *sp = list->array[index].dsize; return list->array[index].dptr; } /* Add an element at the end of a list. */ void cblistpush(CBLIST *list, const char *ptr, int size){ int index; assert(list && ptr); if(size < 0) size = strlen(ptr); index = list->start + list->num; if(index >= list->anum){ list->anum *= 2; CB_REALLOC(list->array, list->anum * sizeof(list->array[0])); } CB_MALLOC(list->array[index].dptr, (size < CB_DATUMUNIT ? CB_DATUMUNIT : size) + 1); memcpy(list->array[index].dptr, ptr, size); list->array[index].dptr[size] = '\0'; list->array[index].dsize = size; list->num++; } /* Remove an element of the end of a list. */ char *cblistpop(CBLIST *list, int *sp){ int index; assert(list); if(list->num < 1) return NULL; index = list->start + list->num - 1; list->num--; if(sp) *sp = list->array[index].dsize; return list->array[index].dptr; } /* Add an element at the top of a list. */ void cblistunshift(CBLIST *list, const char *ptr, int size){ int index; assert(list && ptr); if(size < 0) size = strlen(ptr); if(list->start < 1){ if(list->start + list->num >= list->anum){ list->anum *= 2; CB_REALLOC(list->array, list->anum * sizeof(list->array[0])); } list->start = list->anum - list->num; memmove(list->array + list->start, list->array, list->num * sizeof(list->array[0])); } index = list->start - 1; CB_MALLOC(list->array[index].dptr, (size < CB_DATUMUNIT ? CB_DATUMUNIT : size) + 1); memcpy(list->array[index].dptr, ptr, size); list->array[index].dptr[size] = '\0'; list->array[index].dsize = size; list->start--; list->num++; } /* Remove an element of the top of a list. */ char *cblistshift(CBLIST *list, int *sp){ int index; assert(list); if(list->num < 1) return NULL; index = list->start; list->start++; list->num--; if(sp) *sp = list->array[index].dsize; return list->array[index].dptr; } /* Add an element at the specified location of a list. */ void cblistinsert(CBLIST *list, int index, const char *ptr, int size){ assert(list && index >= 0); if(index > list->num) return; if(size < 0) size = strlen(ptr); index += list->start; if(list->start + list->num >= list->anum){ list->anum *= 2; CB_REALLOC(list->array, list->anum * sizeof(list->array[0])); } memmove(list->array + index + 1, list->array + index, sizeof(list->array[0]) * (list->start + list->num - index)); CB_MEMDUP(list->array[index].dptr, ptr, size); list->array[index].dsize = size; list->num++; } /* Remove an element at the specified location of a list. */ char *cblistremove(CBLIST *list, int index, int *sp){ char *dptr; assert(list && index >= 0); if(index >= list->num) return NULL; index += list->start; dptr = list->array[index].dptr; if(sp) *sp = list->array[index].dsize; list->num--; memmove(list->array + index, list->array + index + 1, sizeof(list->array[0]) * (list->start + list->num - index)); return dptr; } /* Overwrite an element at the specified location of a list. */ void cblistover(CBLIST *list, int index, const char *ptr, int size){ assert(list && index >= 0); if(index >= list->num) return; if(size < 0) size = strlen(ptr); index += list->start; if(size > list->array[index].dsize) CB_REALLOC(list->array[index].dptr, size + 1); memcpy(list->array[index].dptr, ptr, size); list->array[index].dsize = size; list->array[index].dptr[size] = '\0'; } /* Sort elements of a list in lexical order. */ void cblistsort(CBLIST *list){ assert(list); qsort(list->array + list->start, list->num, sizeof(list->array[0]), cblistelemcmp); } /* Search a list for an element using liner search. */ int cblistlsearch(const CBLIST *list, const char *ptr, int size){ int i, end; assert(list && ptr); if(size < 0) size = strlen(ptr); end = list->start + list->num; for(i = list->start; i < end; i++){ if(list->array[i].dsize == size && !memcmp(list->array[i].dptr, ptr, size)) return i - list->start; } return -1; } /* Search a list for an element using binary search. */ int cblistbsearch(const CBLIST *list, const char *ptr, int size){ CBLISTDATUM key, *res; assert(list && ptr); if(size < 0) size = strlen(ptr); CB_MEMDUP(key.dptr, ptr, size); key.dsize = size; res = bsearch(&key, list->array + list->start, list->num, sizeof(list->array[0]), cblistelemcmp); free(key.dptr); return res ? (res - list->array - list->start) : -1; } /* Serialize a list into a byte array. */ char *cblistdump(const CBLIST *list, int *sp){ char *buf, vnumbuf[CB_VNUMBUFSIZ]; const char *vbuf; int i, bsiz, vnumsiz, ln, vsiz; assert(list && sp); ln = CB_LISTNUM(list); CB_SETVNUMBUF(vnumsiz, vnumbuf, ln); CB_MALLOC(buf, vnumsiz + 1); memcpy(buf, vnumbuf, vnumsiz); bsiz = vnumsiz; for(i = 0; i < ln; i++){ vbuf = CB_LISTVAL2(list, i, vsiz); CB_SETVNUMBUF(vnumsiz, vnumbuf, vsiz); CB_REALLOC(buf, bsiz + vnumsiz + vsiz + 1); memcpy(buf + bsiz, vnumbuf, vnumsiz); bsiz += vnumsiz; memcpy(buf + bsiz, vbuf, vsiz); bsiz += vsiz; } *sp = bsiz; return buf; } /* Redintegrate a serialized list. */ CBLIST *cblistload(const char *ptr, int size){ CBLIST *list; const char *rp; int i, anum, step, ln, vsiz; assert(ptr && size >= 0); anum = size / (sizeof(CBLISTDATUM) + 1); CB_LISTOPEN2(list, anum); rp = ptr; CB_READVNUMBUF(rp, size, ln, step); rp += step; size -= step; if(ln > size) return list; for(i = 0; i < ln; i++){ if(size < 1) break; CB_READVNUMBUF(rp, size, vsiz, step); rp += step; size -= step; if(vsiz > size) break; CB_LISTPUSH(list, rp, vsiz); rp += vsiz; } return list; } /* Get a map handle. */ CBMAP *cbmapopen(void){ return cbmapopenex(CB_MAPBNUM); } /* Copy a map. */ CBMAP *cbmapdup(CBMAP *map){ CBMAP *newmap; const char *kbuf, *vbuf; int ksiz, vsiz; assert(map); cbmapiterinit(map); newmap = map->rnum > CB_MAPPBNUM ? cbmapopen() : cbmapopenex(CB_MAPPBNUM); while((kbuf = cbmapiternext(map, &ksiz)) != NULL){ CB_MAPITERVAL(vbuf, kbuf, vsiz); cbmapput(newmap, kbuf, ksiz, vbuf, vsiz, FALSE); } cbmapiterinit(map); return newmap; } /* Close a map handle. */ void cbmapclose(CBMAP *map){ CBMAPDATUM *datum, *next; datum = map->first; while(datum){ next = datum->next; free(datum); datum = next; } free(map->buckets); free(map); } /* Store a record. */ int cbmapput(CBMAP *map, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int over){ CBMAPDATUM *datum, **entp, *old; char *dbuf; int bidx, hash, kcmp, psiz; assert(map && kbuf && vbuf); if(ksiz < 0) ksiz = strlen(kbuf); if(vsiz < 0) vsiz = strlen(vbuf); CB_FIRSTHASH(hash, kbuf, ksiz); bidx = hash % map->bnum; datum = map->buckets[bidx]; entp = map->buckets + bidx; CB_SECONDHASH(hash, kbuf, ksiz); while(datum){ if(hash > datum->hash){ entp = &(datum->left); datum = datum->left; } else if(hash < datum->hash){ entp = &(datum->right); datum = datum->right; } else { dbuf = (char *)datum + sizeof(*datum); kcmp = cbkeycmp(kbuf, ksiz, dbuf, datum->ksiz); if(kcmp < 0){ entp = &(datum->left); datum = datum->left; } else if(kcmp > 0){ entp = &(datum->right); datum = datum->right; } else { if(!over) return FALSE; psiz = CB_ALIGNPAD(ksiz); if(vsiz > datum->vsiz){ old = datum; CB_REALLOC(datum, sizeof(*datum) + ksiz + psiz + vsiz + 1); if(datum != old){ if(map->first == old) map->first = datum; if(map->last == old) map->last = datum; if(*entp == old) *entp = datum; if(datum->prev) datum->prev->next = datum; if(datum->next) datum->next->prev = datum; dbuf = (char *)datum + sizeof(*datum); } } memcpy(dbuf + ksiz + psiz, vbuf, vsiz); dbuf[ksiz+psiz+vsiz] = '\0'; datum->vsiz = vsiz; return TRUE; } } } psiz = CB_ALIGNPAD(ksiz); CB_MALLOC(datum, sizeof(*datum) + ksiz + psiz + vsiz + 1); dbuf = (char *)datum + sizeof(*datum); memcpy(dbuf, kbuf, ksiz); dbuf[ksiz] = '\0'; datum->ksiz = ksiz; memcpy(dbuf + ksiz + psiz, vbuf, vsiz); dbuf[ksiz+psiz+vsiz] = '\0'; datum->vsiz = vsiz; datum->hash = hash; datum->left = NULL; datum->right = NULL; datum->prev = map->last; datum->next = NULL; *entp = datum; if(!map->first) map->first = datum; if(map->last) map->last->next = datum; map->last = datum; map->rnum++; return TRUE; } /* Concatenate a value at the end of the value of the existing record. */ void cbmapputcat(CBMAP *map, const char *kbuf, int ksiz, const char *vbuf, int vsiz){ CBMAPDATUM *datum, **entp, *old; char *dbuf; int bidx, hash, kcmp, psiz, asiz, unit; assert(map && kbuf && vbuf); if(ksiz < 0) ksiz = strlen(kbuf); if(vsiz < 0) vsiz = strlen(vbuf); CB_FIRSTHASH(hash, kbuf, ksiz); bidx = hash % map->bnum; datum = map->buckets[bidx]; entp = map->buckets + bidx; CB_SECONDHASH(hash, kbuf, ksiz); while(datum){ if(hash > datum->hash){ entp = &(datum->left); datum = datum->left; } else if(hash < datum->hash){ entp = &(datum->right); datum = datum->right; } else { dbuf = (char *)datum + sizeof(*datum); kcmp = cbkeycmp(kbuf, ksiz, dbuf, datum->ksiz); if(kcmp < 0){ entp = &(datum->left); datum = datum->left; } else if(kcmp > 0){ entp = &(datum->right); datum = datum->right; } else { psiz = CB_ALIGNPAD(ksiz); asiz = sizeof(*datum) + ksiz + psiz + datum->vsiz + vsiz + 1; unit = asiz <= CB_MAPCSUNIT ? CB_MAPCSUNIT : CB_MAPCBUNIT; asiz = (asiz - 1) + unit - (asiz - 1) % unit; old = datum; CB_REALLOC(datum, asiz); if(datum != old){ if(map->first == old) map->first = datum; if(map->last == old) map->last = datum; if(*entp == old) *entp = datum; if(datum->prev) datum->prev->next = datum; if(datum->next) datum->next->prev = datum; dbuf = (char *)datum + sizeof(*datum); } memcpy(dbuf + ksiz + psiz + datum->vsiz, vbuf, vsiz); dbuf[ksiz+psiz+datum->vsiz+vsiz] = '\0'; datum->vsiz += vsiz; return; } } } psiz = CB_ALIGNPAD(ksiz); asiz = sizeof(*datum) + ksiz + psiz + vsiz + 1; unit = asiz <= CB_MAPCSUNIT ? CB_MAPCSUNIT : CB_MAPCBUNIT; asiz = (asiz - 1) + unit - (asiz - 1) % unit; CB_MALLOC(datum, asiz); dbuf = (char *)datum + sizeof(*datum); memcpy(dbuf, kbuf, ksiz); dbuf[ksiz] = '\0'; datum->ksiz = ksiz; memcpy(dbuf + ksiz + psiz, vbuf, vsiz); dbuf[ksiz+psiz+vsiz] = '\0'; datum->vsiz = vsiz; datum->hash = hash; datum->left = NULL; datum->right = NULL; datum->prev = map->last; datum->next = NULL; *entp = datum; if(!map->first) map->first = datum; if(map->last) map->last->next = datum; map->last = datum; map->rnum++; } /* Delete a record. */ int cbmapout(CBMAP *map, const char *kbuf, int ksiz){ CBMAPDATUM *datum, **entp, *tmp; char *dbuf; int bidx, hash, kcmp; assert(map && kbuf); if(ksiz < 0) ksiz = strlen(kbuf); CB_FIRSTHASH(hash, kbuf, ksiz); bidx = hash % map->bnum; datum = map->buckets[bidx]; entp = map->buckets + bidx; CB_SECONDHASH(hash, kbuf, ksiz); while(datum){ if(hash > datum->hash){ entp = &(datum->left); datum = datum->left; } else if(hash < datum->hash){ entp = &(datum->right); datum = datum->right; } else { dbuf = (char *)datum + sizeof(*datum); kcmp = cbkeycmp(kbuf, ksiz, dbuf, datum->ksiz); if(kcmp < 0){ entp = &(datum->left); datum = datum->left; } else if(kcmp > 0){ entp = &(datum->right); datum = datum->right; } else { if(datum->prev) datum->prev->next = datum->next; if(datum->next) datum->next->prev = datum->prev; if(datum == map->first) map->first = datum->next; if(datum == map->last) map->last = datum->prev; if(datum->left && !datum->right){ *entp = datum->left; } else if(!datum->left && datum->right){ *entp = datum->right; } else if(!datum->left && !datum->left){ *entp = NULL; } else { *entp = datum->left; tmp = *entp; while(TRUE){ if(hash > tmp->hash){ if(tmp->left){ tmp = tmp->left; } else { tmp->left = datum->right; break; } } else if(hash < tmp->hash){ if(tmp->right){ tmp = tmp->right; } else { tmp->right = datum->right; break; } } else { kcmp = cbkeycmp(kbuf, ksiz, dbuf, datum->ksiz); if(kcmp < 0){ if(tmp->left){ tmp = tmp->left; } else { tmp->left = datum->right; break; } } else { if(tmp->right){ tmp = tmp->right; } else { tmp->right = datum->right; break; } } } } } free(datum); map->rnum--; return TRUE; } } } return FALSE; } /* Retrieve a record. */ const char *cbmapget(const CBMAP *map, const char *kbuf, int ksiz, int *sp){ CBMAPDATUM *datum; char *dbuf; int hash, kcmp; assert(map && kbuf); if(ksiz < 0) ksiz = strlen(kbuf); CB_FIRSTHASH(hash, kbuf, ksiz); datum = map->buckets[hash%map->bnum]; CB_SECONDHASH(hash, kbuf, ksiz); while(datum){ if(hash > datum->hash){ datum = datum->left; } else if(hash < datum->hash){ datum = datum->right; } else { dbuf = (char *)datum + sizeof(*datum); kcmp = cbkeycmp(kbuf, ksiz, dbuf, datum->ksiz); if(kcmp < 0){ datum = datum->left; } else if(kcmp > 0){ datum = datum->right; } else { if(sp) *sp = datum->vsiz; return dbuf + datum->ksiz + CB_ALIGNPAD(datum->ksiz); } } } return NULL; } /* Move a record to the edge. */ int cbmapmove(CBMAP *map, const char *kbuf, int ksiz, int head){ CBMAPDATUM *datum; char *dbuf; int hash, kcmp; assert(map && kbuf); if(ksiz < 0) ksiz = strlen(kbuf); CB_FIRSTHASH(hash, kbuf, ksiz); datum = map->buckets[hash%map->bnum]; CB_SECONDHASH(hash, kbuf, ksiz); while(datum){ if(hash > datum->hash){ datum = datum->left; } else if(hash < datum->hash){ datum = datum->right; } else { dbuf = (char *)datum + sizeof(*datum); kcmp = cbkeycmp(kbuf, ksiz, dbuf, datum->ksiz); if(kcmp < 0){ datum = datum->left; } else if(kcmp > 0){ datum = datum->right; } else { if(head){ if(map->first == datum) return TRUE; if(map->last == datum) map->last = datum->prev; if(datum->prev) datum->prev->next = datum->next; if(datum->next) datum->next->prev = datum->prev; datum->prev = NULL; datum->next = map->first; map->first->prev = datum; map->first = datum; } else { if(map->last == datum) return TRUE; if(map->first == datum) map->first = datum->next; if(datum->prev) datum->prev->next = datum->next; if(datum->next) datum->next->prev = datum->prev; datum->prev = map->last; datum->next = NULL; map->last->next = datum; map->last = datum; } return TRUE; } } } return FALSE; } /* Initialize the iterator of a map handle. */ void cbmapiterinit(CBMAP *map){ assert(map); map->cur = map->first; } /* Get the next key of the iterator. */ const char *cbmapiternext(CBMAP *map, int *sp){ CBMAPDATUM *datum; assert(map); if(!map->cur) return NULL; datum = map->cur; map->cur = datum->next; if(sp) *sp = datum->ksiz; return (char *)datum + sizeof(*datum); } /* Get the value binded to the key fetched from the iterator. */ const char *cbmapiterval(const char *kbuf, int *sp){ CBMAPDATUM *datum; assert(kbuf); datum = (CBMAPDATUM *)(kbuf - sizeof(*datum)); if(sp) *sp = datum->vsiz; return (char *)datum + sizeof(*datum) + datum->ksiz + CB_ALIGNPAD(datum->ksiz); } /* Get the number of the records stored in a map. */ int cbmaprnum(const CBMAP *map){ assert(map); return map->rnum; } /* Get the list handle contains all keys in a map. */ CBLIST *cbmapkeys(CBMAP *map){ CBLIST *list; const char *kbuf; int anum, ksiz; assert(map); anum = cbmaprnum(map); CB_LISTOPEN2(list, anum); cbmapiterinit(map); while((kbuf = cbmapiternext(map, &ksiz)) != NULL){ CB_LISTPUSH(list, kbuf, ksiz); } return list; } /* Get the list handle contains all values in a map. */ CBLIST *cbmapvals(CBMAP *map){ CBLIST *list; const char *kbuf, *vbuf; int anum, ksiz, vsiz; assert(map); anum = cbmaprnum(map); CB_LISTOPEN2(list, anum); cbmapiterinit(map); while((kbuf = cbmapiternext(map, &ksiz)) != NULL){ CB_MAPITERVAL(vbuf, kbuf, vsiz); CB_LISTPUSH(list, vbuf, vsiz); } return list; } /* Serialize a map into a byte array. */ char *cbmapdump(CBMAP *map, int *sp){ char *buf, vnumbuf[CB_VNUMBUFSIZ]; const char *kbuf, *vbuf; int bsiz, vnumsiz, rn, ksiz, vsiz; assert(map && sp); rn = cbmaprnum(map); CB_SETVNUMBUF(vnumsiz, vnumbuf, rn); CB_MALLOC(buf, vnumsiz + 1); memcpy(buf, vnumbuf, vnumsiz); bsiz = vnumsiz; cbmapiterinit(map); while((kbuf = cbmapiternext(map, &ksiz)) != NULL){ CB_MAPITERVAL(vbuf, kbuf, vsiz); CB_SETVNUMBUF(vnumsiz, vnumbuf, ksiz); CB_REALLOC(buf, bsiz + vnumsiz + ksiz + 1); memcpy(buf + bsiz, vnumbuf, vnumsiz); bsiz += vnumsiz; memcpy(buf + bsiz, kbuf, ksiz); bsiz += ksiz; CB_SETVNUMBUF(vnumsiz, vnumbuf, vsiz); CB_REALLOC(buf, bsiz + vnumsiz + vsiz + 1); memcpy(buf + bsiz, vnumbuf, vnumsiz); bsiz += vnumsiz; memcpy(buf + bsiz, vbuf, vsiz); bsiz += vsiz; } *sp = bsiz; return buf; } /* Redintegrate a serialized map. */ CBMAP *cbmapload(const char *ptr, int size){ CBMAP *map; const char *rp, *kbuf, *vbuf; int i, step, rn, ksiz, vsiz; assert(ptr && size >= 0); map = cbmapopenex(CB_MAPPBNUM); rp = ptr; CB_READVNUMBUF(rp, size, rn, step); rp += step; size -= step; if(rn > size) return map; for(i = 0; i < rn; i++){ if(size < 1) break; CB_READVNUMBUF(rp, size, ksiz, step); rp += step; size -= step; if(ksiz > size) break; kbuf = rp; rp += ksiz; if(size < 1) break; CB_READVNUMBUF(rp, size, vsiz, step); rp += step; size -= step; if(vsiz > size) break; vbuf = rp; rp += vsiz; cbmapput(map, kbuf, ksiz, vbuf, vsiz, TRUE); } return map; } /* Redintegrate a serialized map and get one of the records. */ char *cbmaploadone(const char *ptr, int size, const char *kbuf, int ksiz, int *sp){ const char *rp, *tkbuf, *vbuf; char *rv; int i, step, rn, tksiz, vsiz; assert(ptr && size >= 0 && kbuf); if(ksiz < 0) ksiz = strlen(kbuf); rp = ptr; CB_READVNUMBUF(rp, size, rn, step); rp += step; size -= step; if(rn > size) return NULL; for(i = 0; i < rn; i++){ if(size < 1) break; CB_READVNUMBUF(rp, size, tksiz, step); rp += step; size -= step; if(tksiz > size) break; tkbuf = rp; rp += tksiz; if(size < 1) break; CB_READVNUMBUF(rp, size, vsiz, step); rp += step; size -= step; if(vsiz > size) break; vbuf = rp; rp += vsiz; if(tksiz == ksiz && !memcmp(tkbuf, kbuf, ksiz)){ if(sp) *sp = vsiz; CB_MEMDUP(rv, vbuf, vsiz); return rv; } } return NULL; } /* Get a heap handle. */ CBHEAP *cbheapopen(int size, int max, int(*compar)(const void *, const void *)){ CBHEAP *heap; assert(size > 0 && max >= 0 && compar); CB_MALLOC(heap, sizeof(*heap)); CB_MALLOC(heap->base, size * max + 1); CB_MALLOC(heap->swap, size); heap->size = size; heap->num = 0; heap->max = max; heap->compar = compar; return heap; } /* Copy a heap. */ CBHEAP *cbheapdup(CBHEAP *heap){ CBHEAP *newheap; assert(heap); CB_MALLOC(newheap, sizeof(*newheap)); CB_MEMDUP(newheap->base, heap->base, heap->size * heap->max); CB_MALLOC(newheap->swap, heap->size); newheap->size = heap->size; newheap->num = heap->num; newheap->max = heap->max; newheap->compar = heap->compar; return newheap; } /* Close a heap handle. */ void cbheapclose(CBHEAP *heap){ assert(heap); free(heap->swap); free(heap->base); free(heap); } /* Get the number of the records stored in a heap. */ int cbheapnum(CBHEAP *heap){ assert(heap); return heap->num; } /* Insert a record into a heap. */ int cbheapinsert(CBHEAP *heap, const void *ptr){ char *base; int size, pidx, cidx, bot; assert(heap && ptr); if(heap->max < 1) return FALSE; base = heap->base; size = heap->size; if(heap->num >= heap->max){ if(heap->compar(ptr, base) > 0) return FALSE; memcpy(base, ptr, size); pidx = 0; bot = heap->num / 2; while(pidx < bot){ cidx = pidx * 2 + 1; if(cidx < heap->num - 1 && heap->compar(base + cidx * size, base + (cidx + 1) * size) < 0) cidx++; if(heap->compar(base + pidx * size, base + cidx * size) > 0) break; memcpy(heap->swap, base + pidx * size, size); memcpy(base + pidx * size, base + cidx * size, size); memcpy(base + cidx * size, heap->swap, size); pidx = cidx; } } else { memcpy(base + size * heap->num, ptr, size); cidx = heap->num; while(cidx > 0){ pidx = (cidx - 1) / 2; if(heap->compar(base + cidx * size, base + pidx * size) <= 0) break; memcpy(heap->swap, base + cidx * size, size); memcpy(base + cidx * size, base + pidx * size, size); memcpy(base + pidx * size, heap->swap, size); cidx = pidx; } heap->num++; } return TRUE; } /* Get the pointer to the region of a record in a heap. */ const void *cbheapval(CBHEAP *heap, int index){ assert(heap && index >= 0); if(index >= heap->num) return NULL; return heap->base + index * heap->size; } /* Convert a heap to an allocated region. */ void *cbheaptomalloc(CBHEAP *heap, int *np){ char *ptr; assert(heap); qsort(heap->base, heap->num, heap->size, heap->compar); ptr = heap->base; if(np) *np = heap->num; free(heap->swap); free(heap); return ptr; } /* Allocate a formatted string on memory. */ char *cbsprintf(const char *format, ...){ va_list ap; char *buf, cbuf[CB_SPBUFSIZ], *str; int len, cblen, num, slen; unsigned int unum; double dnum; va_start(ap, format); assert(format); CB_MALLOC(buf, 1); len = 0; while(*format != '\0'){ if(*format == '%'){ cbuf[0] = '%'; cblen = 1; format++; while(strchr("0123456789 .+-", *format) && *format != '\0' && cblen < CB_SPBUFSIZ - 1){ cbuf[cblen++] = *format; format++; } cbuf[cblen] = '\0'; if(atoi(cbuf + 1) > CB_SPMAXWIDTH - 16){ sprintf(cbuf, "(err)"); } else { cbuf[cblen++] = *format; cbuf[cblen] = '\0'; } switch(*format){ case 'd': num = va_arg(ap, int); CB_REALLOC(buf, len + CB_SPMAXWIDTH + 2); len += sprintf(buf + len, cbuf, num); break; case 'o': case 'u': case 'x': case 'X': case 'c': unum = va_arg(ap, unsigned int); CB_REALLOC(buf, len + CB_SPMAXWIDTH + 2); len += sprintf(buf + len, cbuf, unum); break; case 'e': case 'E': case 'f': case 'g': case 'G': dnum = va_arg(ap, double); CB_REALLOC(buf, len + CB_SPMAXWIDTH + 2); len += sprintf(buf + len, cbuf, dnum); break; case 's': str = va_arg(ap, char *); slen = strlen(str); CB_REALLOC(buf, len + slen + 2); memcpy(buf + len, str, slen); len += slen; break; case '%': CB_REALLOC(buf, len + 2); buf[len++] = '%'; break; default: break; } } else { CB_REALLOC(buf, len + 2); buf[len++] = *format; } format++; } buf[len] = '\0'; va_end(ap); return buf; } /* Replace some patterns in a string. */ char *cbreplace(const char *str, CBMAP *pairs){ int i, bsiz, wi, rep, ksiz, vsiz; char *buf; const char *key, *val; assert(str && pairs); bsiz = CB_DATUMUNIT; CB_MALLOC(buf, bsiz); wi = 0; while(*str != '\0'){ rep = FALSE; cbmapiterinit(pairs); while((key = cbmapiternext(pairs, &ksiz)) != NULL){ for(i = 0; i < ksiz; i++){ if(str[i] == '\0' || str[i] != key[i]) break; } if(i == ksiz){ CB_MAPITERVAL(val, key, vsiz); if(wi + vsiz >= bsiz){ bsiz = bsiz * 2 + vsiz; CB_REALLOC(buf, bsiz); } memcpy(buf + wi, val, vsiz); wi += vsiz; str += ksiz; rep = TRUE; break; } } if(!rep){ if(wi + 1 >= bsiz){ bsiz = bsiz * 2 + 1; CB_REALLOC(buf, bsiz); } buf[wi++] = *str; str++; } } CB_REALLOC(buf, wi + 1); buf[wi] = '\0'; return buf; } /* Make a list by split a serial datum. */ CBLIST *cbsplit(const char *ptr, int size, const char *delim){ CBLIST *list; int bi, step; assert(ptr); CB_LISTOPEN(list); if(size < 0) size = strlen(ptr); if(delim){ for(bi = 0; bi < size; bi += step){ step = 0; while(bi + step < size && !strchr(delim, ptr[bi+step])){ step++; } cblistpush(list, ptr + bi, step); step++; } if(size > 0 && strchr(delim, ptr[size-1])) cblistpush(list, "", 0); } else { for(bi = 0; bi < size; bi += step){ step = 0; while(bi + step < size && ptr[bi+step]){ step++; } cblistpush(list, ptr + bi, step); step++; } if(size > 0 && ptr[size-1] == 0) cblistpush(list, "", 0); } return list; } /* Read whole data of a file. */ char *cbreadfile(const char *name, int *sp){ struct stat sbuf; char iobuf[CB_IOBUFSIZ], *buf; int fd, size, asiz, rv; asiz = CB_IOBUFSIZ * 2; if(name){ if((fd = open(name, O_RDONLY, 0)) == -1) return NULL; if(fstat(fd, &sbuf) != -1) asiz = sbuf.st_size + 1; } else { fd = 0; } CB_MALLOC(buf, asiz + 1); size = 0; while((rv = read(fd, iobuf, CB_IOBUFSIZ)) > 0){ if(size + rv >= asiz){ asiz = asiz * 2 + size; CB_REALLOC(buf, asiz + 1); } memcpy(buf + size, iobuf, rv); size += rv; } buf[size] = '\0'; if(close(fd) == -1 || rv == -1){ free(buf); return NULL; } if(sp) *sp = size; return buf; } /* Write data of a region into a file. */ int cbwritefile(const char *name, const char *ptr, int size){ int fd, err, wb; assert(ptr); if(size < 0) size = strlen(ptr); if(name){ if((fd = open(name, O_WRONLY | O_CREAT | O_TRUNC, CB_FILEMODE)) == -1) return FALSE; } else { fd = 1; } err = FALSE; wb = 0; do { wb = write(fd, ptr, size); switch(wb){ case -1: err = errno != EINTR ? TRUE : FALSE; break; case 0: break; default: ptr += wb; size -= wb; break; } } while(size > 0); if(close(fd) == -1) err = TRUE; return err ? FALSE : TRUE; } /* Read every line of a file. */ CBLIST *cbreadlines(const char *name){ char *buf, *tmp; int vsiz; CBMAP *pairs; CBLIST *list; if(!(buf = cbreadfile(name, NULL))) return NULL; pairs = cbmapopenex(3); cbmapput(pairs, "\r\n", 2, "\n", 1, TRUE); cbmapput(pairs, "\r", 1, "\n", 1, TRUE); tmp = cbreplace(buf, pairs); list = cbsplit(tmp, strlen(tmp), "\n"); free(tmp); cbmapclose(pairs); free(buf); if(CB_LISTNUM(list) > 0){ cblistval(list, CB_LISTNUM(list) - 1, &vsiz); if(vsiz < 1) CB_LISTDROP(list); } return list; } /* Read names of files in a directory. */ CBLIST *cbdirlist(const char *name){ DIR *DD; struct dirent *dp; CBLIST *list; assert(name); if(!(DD = opendir(name))) return NULL; CB_LISTOPEN(list); while((dp = readdir(DD)) != NULL){ CB_LISTPUSH(list, dp->d_name, strlen(dp->d_name)); } if(closedir(DD) == -1){ CB_LISTCLOSE(list); return NULL; } return list; } /* Get the status of a file or a directory. */ int cbfilestat(const char *name, int *isdirp, int *sizep, time_t *mtimep){ struct stat sbuf; assert(name); if(lstat(name, &sbuf) == -1) return FALSE; if(isdirp) *isdirp = S_ISDIR(sbuf.st_mode); if(sizep) *sizep = (int)sbuf.st_size; if(mtimep) *mtimep = sbuf.st_mtime; return TRUE; } /* Remove a file or a directory and its sub ones recursively. */ int cbremove(const char *name){ CBLIST *list; const char *elem; char *path; int i, err, tail; struct stat sbuf; assert(name); if(lstat(name, &sbuf) == -1) return FALSE; if(unlink(name) == 0) return TRUE; if(!S_ISDIR(sbuf.st_mode) || !(list = cbdirlist(name))) return FALSE; err = FALSE; tail = name[0] != '\0' && name[strlen(name)-1] == MYPATHCHR; for(i = 0; i < CB_LISTNUM(list); i++){ elem = CB_LISTVAL(list, i); if(!strcmp(MYCDIRSTR, elem) || !strcmp(MYPDIRSTR, elem)) continue; if(tail){ path = cbsprintf("%s%s", name, elem); } else { path = cbsprintf("%s%c%s", name, MYPATHCHR, elem); } if(!cbremove(path)) err = TRUE; free(path); } CB_LISTCLOSE(list); return rmdir(name) == 0 ? TRUE : FALSE; } /* Break up a URL into elements. */ CBMAP *cburlbreak(const char *str){ CBMAP *map; char *tmp, *ep; const char *rp; int serv; assert(str); map = cbmapopenex(CB_MAPPBNUM); CB_MEMDUP(tmp, str, strlen(str)); rp = cbstrtrim(tmp); cbmapput(map, "self", -1, rp, -1, TRUE); serv = FALSE; if(cbstrfwimatch(rp, "http://")){ cbmapput(map, "scheme", -1, "http", -1, TRUE); rp += 7; serv = TRUE; } else if(cbstrfwimatch(rp, "https://")){ cbmapput(map, "scheme", -1, "https", -1, TRUE); rp += 8; serv = TRUE; } else if(cbstrfwimatch(rp, "ftp://")){ cbmapput(map, "scheme", -1, "ftp", -1, TRUE); rp += 6; serv = TRUE; } else if(cbstrfwimatch(rp, "sftp://")){ cbmapput(map, "scheme", -1, "sftp", -1, TRUE); rp += 7; serv = TRUE; } else if(cbstrfwimatch(rp, "ftps://")){ cbmapput(map, "scheme", -1, "ftps", -1, TRUE); rp += 7; serv = TRUE; } else if(cbstrfwimatch(rp, "tftp://")){ cbmapput(map, "scheme", -1, "tftp", -1, TRUE); rp += 7; serv = TRUE; } else if(cbstrfwimatch(rp, "ldap://")){ cbmapput(map, "scheme", -1, "ldap", -1, TRUE); rp += 7; serv = TRUE; } else if(cbstrfwimatch(rp, "ldaps://")){ cbmapput(map, "scheme", -1, "ldaps", -1, TRUE); rp += 8; serv = TRUE; } else if(cbstrfwimatch(rp, "file://")){ cbmapput(map, "scheme", -1, "file", -1, TRUE); rp += 7; serv = TRUE; } if((ep = strchr(rp, '#')) != NULL){ cbmapput(map, "fragment", -1, ep + 1, -1, TRUE); *ep = '\0'; } if((ep = strchr(rp, '?')) != NULL){ cbmapput(map, "query", -1, ep + 1, -1, TRUE); *ep = '\0'; } if(serv){ if((ep = strchr(rp, '/')) != NULL){ cbmapput(map, "path", -1, ep, -1, TRUE); *ep = '\0'; } else { cbmapput(map, "path", -1, "/", -1, TRUE); } if((ep = strchr(rp, '@')) != NULL){ *ep = '\0'; if(rp[0] != '\0') cbmapput(map, "authority", -1, rp, -1, TRUE); rp = ep + 1; } if((ep = strchr(rp, ':')) != NULL){ if(ep[1] != '\0') cbmapput(map, "port", -1, ep + 1, -1, TRUE); *ep = '\0'; } if(rp[0] != '\0') cbmapput(map, "host", -1, rp, -1, TRUE); } else { cbmapput(map, "path", -1, rp, -1, TRUE); } free(tmp); if((rp = cbmapget(map, "path", -1, NULL)) != NULL){ if((ep = strrchr(rp, '/')) != NULL){ if(ep[1] != '\0') cbmapput(map, "file", -1, ep + 1, -1, TRUE); } else { cbmapput(map, "file", -1, rp, -1, TRUE); } } if((rp = cbmapget(map, "file", -1, NULL)) != NULL && (!strcmp(rp, ".") || !strcmp(rp, ".."))) cbmapout(map, "file", -1); return map; } /* Resolve a relative URL with another absolute URL. */ char *cburlresolve(const char *base, const char *target){ CBMAP *telems, *belems; CBLIST *bpaths, *opaths, *qelems; CBDATUM *rbuf; const char *vbuf, *path; char *tmp, *wp, *enc, numbuf[CB_NUMBUFSIZ]; int i, vsiz, port, num; assert(base && target); while(*base > '\0' && *base <= ' '){ base++; } while(*target > '\0' && *target <= ' '){ target++; } if(*target == '\0') target = base; CB_DATUMOPEN(rbuf); telems = cburlbreak(target); port = 80; belems = cburlbreak(cbmapget(telems, "scheme", -1, &vsiz) ? target : base); if((vbuf = cbmapget(belems, "scheme", -1, &vsiz)) != NULL){ CB_DATUMCAT(rbuf, vbuf, vsiz); CB_DATUMCAT(rbuf, "://", 3); if(!cbstricmp(vbuf, "https")){ port = 443; } else if(!cbstricmp(vbuf, "ftp")){ port = 21; } else if(!cbstricmp(vbuf, "sftp")){ port = 115; } else if(!cbstricmp(vbuf, "ftps")){ port = 22; } else if(!cbstricmp(vbuf, "tftp")){ port = 69; } else if(!cbstricmp(vbuf, "ldap")){ port = 389; } else if(!cbstricmp(vbuf, "ldaps")){ port = 636; } } else { CB_DATUMCAT(rbuf, "http://", 7); } if((vbuf = cbmapget(belems, "authority", -1, &vsiz)) != NULL){ if((wp = strchr(vbuf, ':')) != NULL){ *wp = '\0'; tmp = cburldecode(vbuf, NULL); enc = cburlencode(tmp, -1); CB_DATUMCAT(rbuf, enc, strlen(enc)); free(enc); free(tmp); CB_DATUMCAT(rbuf, ":", 1); wp++; tmp = cburldecode(wp, NULL); enc = cburlencode(tmp, -1); CB_DATUMCAT(rbuf, enc, strlen(enc)); free(enc); free(tmp); } else { tmp = cburldecode(vbuf, NULL); enc = cburlencode(tmp, -1); CB_DATUMCAT(rbuf, enc, strlen(enc)); free(enc); free(tmp); } CB_DATUMCAT(rbuf, "@", 1); } if((vbuf = cbmapget(belems, "host", -1, &vsiz)) != NULL){ tmp = cburldecode(vbuf, NULL); cbstrtolower(tmp); enc = cburlencode(tmp, -1); CB_DATUMCAT(rbuf, enc, strlen(enc)); free(enc); free(tmp); } else { CB_DATUMCAT(rbuf, "localhost", 9); } if((vbuf = cbmapget(belems, "port", -1, &vsiz)) != NULL && (num = atoi(vbuf)) != port && num > 1){ sprintf(numbuf, ":%d", num); CB_DATUMCAT(rbuf, numbuf, strlen(numbuf)); } if(!(path = cbmapget(telems, "path", -1, NULL))) path = "/"; if(path[0] == '\0' && (vbuf = cbmapget(belems, "path", -1, NULL)) != NULL) path = vbuf; if(path[0] == '\0') path = "/"; CB_LISTOPEN(bpaths); if(path[0] != '/' && (vbuf = cbmapget(belems, "path", -1, &vsiz)) != NULL){ opaths = cbsplit(vbuf, vsiz, "/"); } else { opaths = cbsplit("/", 1, "/"); } CB_LISTDROP(opaths); for(i = 0; i < CB_LISTNUM(opaths); i++){ vbuf = CB_LISTVAL2(opaths, i, vsiz); if(vsiz < 1 || !strcmp(vbuf, ".")) continue; if(!strcmp(vbuf, "..")){ CB_LISTDROP(bpaths); } else { CB_LISTPUSH(bpaths, vbuf, vsiz); } } CB_LISTCLOSE(opaths); opaths = cbsplit(path, -1, "/"); for(i = 0; i < CB_LISTNUM(opaths); i++){ vbuf = CB_LISTVAL2(opaths, i, vsiz); if(vsiz < 1 || !strcmp(vbuf, ".")) continue; if(!strcmp(vbuf, "..")){ CB_LISTDROP(bpaths); } else { CB_LISTPUSH(bpaths, vbuf, vsiz); } } CB_LISTCLOSE(opaths); for(i = 0; i < CB_LISTNUM(bpaths); i++){ vbuf = CB_LISTVAL(bpaths, i); if(strchr(vbuf, '%')){ tmp = cburldecode(vbuf, NULL); } else { CB_MEMDUP(tmp, vbuf, strlen(vbuf)); } enc = cburlencode(tmp, -1); CB_DATUMCAT(rbuf, "/", 1); CB_DATUMCAT(rbuf, enc, strlen(enc)); free(enc); free(tmp); } if(cbstrbwmatch(path, "/")) CB_DATUMCAT(rbuf, "/", 1); CB_LISTCLOSE(bpaths); if((vbuf = cbmapget(telems, "query", -1, &vsiz)) != NULL){ CB_DATUMCAT(rbuf, "?", 1); qelems = cbsplit(vbuf, vsiz, "&;"); for(i = 0; i < CB_LISTNUM(qelems); i++){ vbuf = CB_LISTVAL(qelems, i); if(i > 0) CB_DATUMCAT(rbuf, "&", 1); if((wp = strchr(vbuf, '=')) != NULL){ *wp = '\0'; tmp = cburldecode(vbuf, NULL); enc = cburlencode(tmp, -1); CB_DATUMCAT(rbuf, enc, strlen(enc)); free(enc); free(tmp); CB_DATUMCAT(rbuf, "=", 1); wp++; tmp = cburldecode(wp, NULL); enc = cburlencode(tmp, -1); CB_DATUMCAT(rbuf, enc, strlen(enc)); free(enc); free(tmp); } else { tmp = cburldecode(vbuf, NULL); enc = cburlencode(tmp, -1); CB_DATUMCAT(rbuf, enc, strlen(enc)); free(enc); free(tmp); } } CB_LISTCLOSE(qelems); } if((vbuf = cbmapget(telems, "fragment", -1, &vsiz)) != NULL){ tmp = cburldecode(vbuf, NULL); enc = cburlencode(tmp, -1); CB_DATUMCAT(rbuf, "#", 1); CB_DATUMCAT(rbuf, enc, strlen(enc)); free(enc); free(tmp); } cbmapclose(belems); cbmapclose(telems); return cbdatumtomalloc(rbuf, NULL); } /* Encode a serial object with URL encoding. */ char *cburlencode(const char *ptr, int size){ char *buf, *wp; int i, c; assert(ptr); if(size < 0) size = strlen(ptr); CB_MALLOC(buf, size * 3 + 1); wp = buf; for(i = 0; i < size; i++){ c = ((unsigned char *)ptr)[i]; if((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || (c != '\0' && strchr("_-.!~*'()", c))){ *(wp++) = c; } else { wp += sprintf(wp, "%%%02X", c); } } *wp = '\0'; return buf; } /* Decode a string encoded with URL encoding. */ char *cburldecode(const char *str, int *sp){ char *buf, *wp; unsigned char c; CB_MEMDUP(buf, str, strlen(str)); wp = buf; while(*str != '\0'){ if(*str == '%'){ str++; if(((str[0] >= '0' && str[0] <= '9') || (str[0] >= 'A' && str[0] <= 'F') || (str[0] >= 'a' && str[0] <= 'f')) && ((str[1] >= '0' && str[1] <= '9') || (str[1] >= 'A' && str[1] <= 'F') || (str[1] >= 'a' && str[1] <= 'f'))){ c = *str; if(c >= 'A' && c <= 'Z') c += 'a' - 'A'; if(c >= 'a' && c <= 'z'){ *wp = c - 'a' + 10; } else { *wp = c - '0'; } *wp *= 0x10; str++; c = *str; if(c >= 'A' && c <= 'Z') c += 'a' - 'A'; if(c >= 'a' && c <= 'z'){ *wp += c - 'a' + 10; } else { *wp += c - '0'; } str++; wp++; } else { break; } } else if(*str == '+'){ *wp = ' '; str++; wp++; } else { *wp = *str; str++; wp++; } } *wp = '\0'; if(sp) *sp = wp - buf; return buf; } /* Encode a serial object with Base64 encoding. */ char *cbbaseencode(const char *ptr, int size){ char *tbl = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; char *buf, *wp; const unsigned char *obj; int i; assert(ptr); if(size < 0) size = strlen(ptr); CB_MALLOC(buf, 4 * (size + 2) / 3 + 1); obj = (const unsigned char *)ptr; wp = buf; for(i = 0; i < size; i += 3){ switch(size - i){ case 1: *wp++ = tbl[obj[0] >> 2]; *wp++ = tbl[(obj[0] & 3) << 4]; *wp++ = '='; *wp++ = '='; break; case 2: *wp++ = tbl[obj[0] >> 2]; *wp++ = tbl[((obj[0] & 3) << 4) + (obj[1] >> 4)]; *wp++ = tbl[(obj[1] & 0xf) << 2]; *wp++ = '='; break; default: *wp++ = tbl[obj[0] >> 2]; *wp++ = tbl[((obj[0] & 3) << 4) + (obj[1] >> 4)]; *wp++ = tbl[((obj[1] & 0xf) << 2) + (obj[2] >> 6)]; *wp++ = tbl[obj[2] & 0x3f]; break; } obj += 3; } *wp = '\0'; return buf; } /* Decode a string encoded with Base64 encoding. */ char *cbbasedecode(const char *str, int *sp){ unsigned char *obj, *wp; int len, cnt, bpos, i, bits, eqcnt; assert(str); cnt = 0; bpos = 0; eqcnt = 0; len = strlen(str); CB_MALLOC(obj, len + 4); wp = obj; while(bpos < len && eqcnt == 0){ bits = 0; for(i = 0; bpos < len && i < 4; bpos++){ if(str[bpos] >= 'A' && str[bpos] <= 'Z'){ bits = (bits << 6) | (str[bpos] - 'A'); i++; } else if(str[bpos] >= 'a' && str[bpos] <= 'z'){ bits = (bits << 6) | (str[bpos] - 'a' + 26); i++; } else if(str[bpos] >= '0' && str[bpos] <= '9'){ bits = (bits << 6) | (str[bpos] - '0' + 52); i++; } else if(str[bpos] == '+'){ bits = (bits << 6) | 62; i++; } else if(str[bpos] == '/'){ bits = (bits << 6) | 63; i++; } else if(str[bpos] == '='){ bits <<= 6; i++; eqcnt++; } } if(i == 0 && bpos >= len) continue; switch(eqcnt){ case 0: *wp++ = (bits >> 16) & 0xff; *wp++ = (bits >> 8) & 0xff; *wp++ = bits & 0xff; cnt += 3; break; case 1: *wp++ = (bits >> 16) & 0xff; *wp++ = (bits >> 8) & 0xff; cnt += 2; break; case 2: *wp++ = (bits >> 16) & 0xff; cnt += 1; break; } } obj[cnt] = '\0'; if(sp) *sp = cnt; return (char *)obj; } /* Encode a serial object with quoted-printable encoding. */ char *cbquoteencode(const char *ptr, int size){ const unsigned char *rp; char *buf, *wp; int i, cols; assert(ptr); if(size < 0) size = strlen(ptr); rp = (const unsigned char *)ptr; CB_MALLOC(buf, size * 3 + 1); wp = buf; cols = 0; for(i = 0; i < size; i++){ if(rp[i] == '=' || (rp[i] < 0x20 && rp[i] != '\r' && rp[i] != '\n' && rp[i] != '\t') || rp[i] > 0x7e){ wp += sprintf(wp, "=%02X", rp[i]); cols += 3; } else { *(wp++) = rp[i]; cols++; } } *wp = '\0'; return buf; } /* Decode a string encoded with quoted-printable encoding. */ char *cbquotedecode(const char *str, int *sp){ char *buf, *wp; assert(str); CB_MALLOC(buf, strlen(str) + 1); wp = buf; for(; *str != '\0'; str++){ if(*str == '='){ str++; if(*str == '\0'){ break; } else if(str[0] == '\r' && str[1] == '\n'){ str++; } else if(str[0] != '\n' && str[0] != '\r'){ if(*str >= 'A' && *str <= 'Z'){ *wp = (*str - 'A' + 10) * 16; } else if(*str >= 'a' && *str <= 'z'){ *wp = (*str - 'a' + 10) * 16; } else { *wp = (*str - '0') * 16; } str++; if(*str == '\0') break; if(*str >= 'A' && *str <= 'Z'){ *wp += *str - 'A' + 10; } else if(*str >= 'a' && *str <= 'z'){ *wp += *str - 'a' + 10; } else { *wp += *str - '0'; } wp++; } } else { *wp = *str; wp++; } } *wp = '\0'; if(sp) *sp = wp - buf; return buf; } /* Split a string of MIME into headers and the body. */ char *cbmimebreak(const char *ptr, int size, CBMAP *attrs, int *sp){ CBLIST *list; const char *head, *line, *pv, *ep; char *hbuf, *name, *rv; int i, j, wi, hlen; assert(ptr); if(size < 0) size = strlen(ptr); head = NULL; hlen = 0; for(i = 0; i < size; i++){ if(i < size - 4 && ptr[i] == '\r' && ptr[i+1] == '\n' && ptr[i+2] == '\r' && ptr[i+3] == '\n'){ head = ptr; hlen = i; ptr += i + 4; size -= i + 4; break; } else if(i < size - 2 && ptr[i] == '\n' && ptr[i+1] == '\n'){ head = ptr; hlen = i; ptr += i + 2; size -= i + 2; break; } } if(head && attrs){ CB_MALLOC(hbuf, hlen + 1); wi = 0; for(i = 0; i < hlen; i++){ if(head[i] == '\r') continue; if(i < hlen - 1 && head[i] == '\n' && (head[i+1] == ' ' || head[i+1] == '\t')){ hbuf[wi++] = ' '; i++; } else { hbuf[wi++] = head[i]; } } list = cbsplit(hbuf, wi, "\n"); for(i = 0; i < CB_LISTNUM(list); i++){ line = CB_LISTVAL(list, i); if((pv = strchr(line, ':')) != NULL){ CB_MEMDUP(name, line, pv - line); for(j = 0; name[j] != '\0'; j++){ if(name[j] >= 'A' && name[j] <= 'Z') name[j] -= 'A' - 'a'; } pv++; while(*pv == ' ' || *pv == '\t'){ pv++; } cbmapput(attrs, name, -1, pv, -1, TRUE); free(name); } } CB_LISTCLOSE(list); free(hbuf); if((pv = cbmapget(attrs, "content-type", -1, NULL)) != NULL){ if((ep = strchr(pv, ';')) != NULL){ cbmapput(attrs, "TYPE", -1, pv, ep - pv, TRUE); do { ep++; while(ep[0] == ' '){ ep++; } if(cbstrfwimatch(ep, "charset=")){ ep += 8; while(*ep > '\0' && *ep <= ' '){ ep++; } if(ep[0] == '"') ep++; pv = ep; while(ep[0] != '\0' && ep[0] != ' ' && ep[0] != '"' && ep[0] != ';'){ ep++; } cbmapput(attrs, "CHARSET", -1, pv, ep - pv, TRUE); } else if(cbstrfwimatch(ep, "boundary=")){ ep += 9; while(*ep > '\0' && *ep <= ' '){ ep++; } if(ep[0] == '"'){ ep++; pv = ep; while(ep[0] != '\0' && ep[0] != '"'){ ep++; } } else { pv = ep; while(ep[0] != '\0' && ep[0] != ' ' && ep[0] != '"' && ep[0] != ';'){ ep++; } } cbmapput(attrs, "BOUNDARY", -1, pv, ep - pv, TRUE); } } while((ep = strchr(ep, ';')) != NULL); } else { cbmapput(attrs, "TYPE", -1, pv, -1, TRUE); } } if((pv = cbmapget(attrs, "content-disposition", -1, NULL)) != NULL){ if((ep = strchr(pv, ';')) != NULL){ cbmapput(attrs, "DISPOSITION", -1, pv, ep - pv, TRUE); do { ep++; while(ep[0] == ' '){ ep++; } if(cbstrfwimatch(ep, "filename=")){ ep += 9; if(ep[0] == '"') ep++; pv = ep; while(ep[0] != '\0' && ep[0] != '"'){ ep++; } cbmapput(attrs, "FILENAME", -1, pv, ep - pv, TRUE); } else if(cbstrfwimatch(ep, "name=")){ ep += 5; if(ep[0] == '"') ep++; pv = ep; while(ep[0] != '\0' && ep[0] != '"'){ ep++; } cbmapput(attrs, "NAME", -1, pv, ep - pv, TRUE); } } while((ep = strchr(ep, ';')) != NULL); } else { cbmapput(attrs, "DISPOSITION", -1, pv, -1, TRUE); } } } if(sp) *sp = size; CB_MEMDUP(rv, ptr, size); return rv; } /* Split multipart data in MIME into its parts. */ CBLIST *cbmimeparts(const char *ptr, int size, const char *boundary){ CBLIST *list; const char *pv, *ep; int i, blen; assert(ptr && boundary); if(size < 0) size = strlen(ptr); CB_LISTOPEN(list); if((blen = strlen(boundary)) < 1) return list; pv = NULL; for(i = 0; i < size; i++){ if(ptr[i] == '-' && ptr[i+1] == '-' && i + 2 + blen < size && cbstrfwmatch(ptr + i + 2, boundary) && strchr("\t\n\v\f\r ", ptr[i+2+blen])){ pv = ptr + i + 2 + blen; if(*pv == '\r') pv++; if(*pv == '\n') pv++; size -= pv - ptr; ptr = pv; break; } } if(!pv) return list; for(i = 0; i < size; i++){ if(ptr[i] == '-' && ptr[i+1] == '-' && i + 2 + blen < size && cbstrfwmatch(ptr + i + 2, boundary) && strchr("\t\n\v\f\r -", ptr[i+2+blen])){ ep = ptr + i; if(ep > ptr && ep[-1] == '\n') ep--; if(ep > ptr && ep[-1] == '\r') ep--; if(ep > pv) CB_LISTPUSH(list, pv, ep - pv); pv = ptr + i + 2 + blen; if(*pv == '\r') pv++; if(*pv == '\n') pv++; } } return list; } /* Encode a string with MIME encoding. */ char *cbmimeencode(const char *str, const char *encname, int base){ char *buf, *wp, *enc; int len; assert(str && encname); len = strlen(str); CB_MALLOC(buf, len * 3 + strlen(encname) + 16); wp = buf; wp += sprintf(wp, "=?%s?%c?", encname, base ? 'B' : 'Q'); enc = base ? cbbaseencode(str, len) : cbquoteencode(str, len); wp += sprintf(wp, "%s?=", enc); free(enc); return buf; } /* Decode a string encoded with MIME encoding. */ char *cbmimedecode(const char *str, char *enp){ char *buf, *wp, *tmp, *dec; const char *pv, *ep; int quoted; assert(str); if(enp) sprintf(enp, "US-ASCII"); CB_MALLOC(buf, strlen(str) + 1); wp = buf; while(*str != '\0'){ if(cbstrfwmatch(str, "=?")){ str += 2; pv = str; if(!(ep = strchr(str, '?'))) continue; if(enp && ep - pv < CB_ENCBUFSIZ){ memcpy(enp, pv, ep - pv); enp[ep-pv] = '\0'; } pv = ep + 1; quoted = (*pv == 'Q' || *pv == 'q'); if(*pv != '\0') pv++; if(*pv != '\0') pv++; if(!(ep = strchr(pv, '?'))) continue; CB_MEMDUP(tmp, pv, ep - pv); dec = quoted ? cbquotedecode(tmp, NULL) : cbbasedecode(tmp, NULL); wp += sprintf(wp, "%s", dec); free(dec); free(tmp); str = ep + 1; if(*str != '\0') str++; } else { *(wp++) = *str; str++; } } *wp = '\0'; return buf; } /* Split a string of CSV into rows. */ CBLIST *cbcsvrows(const char *str){ CBLIST *list; const char *pv; int quoted; assert(str); CB_LISTOPEN(list); pv = str; quoted = FALSE; while(TRUE){ if(*str == '"') quoted = !quoted; if(!quoted && (*str == '\r' || *str == '\n')){ CB_LISTPUSH(list, pv, str - pv); if(str[0] == '\r' && str[1] == '\n') str++; str++; pv = str; } else if(*str == '\0'){ if(str > pv) CB_LISTPUSH(list, pv, str - pv); break; } else { str++; } } return list; } /* Split a string of a row of CSV into cells. */ CBLIST *cbcsvcells(const char *str){ CBLIST *list, *uelist; const char *pv; char *tmp; int i, quoted; assert(str); CB_LISTOPEN(list); pv = str; quoted = FALSE; while(TRUE){ if(*str == '"') quoted = !quoted; if(!quoted && *str == ','){ CB_LISTPUSH(list, pv, str - pv); str++; pv = str; } else if(*str == '\0'){ CB_LISTPUSH(list, pv, str - pv); break; } else { str++; } } CB_LISTOPEN(uelist); for(i = 0; i < CB_LISTNUM(list); i++){ tmp = cbcsvunescape(CB_LISTVAL(list, i)); CB_LISTPUSH(uelist, tmp, strlen(tmp)); free(tmp); } CB_LISTCLOSE(list); return uelist; } /* Escape a string with the meta characters of CSV. */ char *cbcsvescape(const char *str){ char *buf, *wp; int i; assert(str); CB_MALLOC(buf, strlen(str) * 2 + 3); wp = buf; *(wp++) = '"'; for(i = 0; str[i] != '\0'; i++){ if(str[i] == '"') *(wp++) = '"'; *(wp++) = str[i]; } *(wp++) = '"'; *wp = '\0'; return buf; } /* Unescape a string with the escaped meta characters of CSV. */ char *cbcsvunescape(const char *str){ char *buf, *wp; int i, len; assert(str); len = strlen(str); if(str[0] == '"'){ str++; len--; if(str[len-1] == '"') len--; } CB_MALLOC(buf, len + 1); wp = buf; for(i = 0; i < len; i++){ if(str[i] == '"'){ if(str[i+1] == '"') *(wp++) = str[i++]; } else { *(wp++) = str[i]; } } *wp = '\0'; return buf; } /* Split a string of XML into tags and text sections. */ CBLIST *cbxmlbreak(const char *str, int cr){ CBLIST *list; CBDATUM *datum; int i, pv, tag; char *ep; assert(str); CB_LISTOPEN(list); i = 0; pv = 0; tag = FALSE; while(TRUE){ if(str[i] == '\0'){ if(i > pv) CB_LISTPUSH(list, str + pv, i - pv); break; } else if(!tag && str[i] == '<'){ if(str[i+1] == '!' && str[i+2] == '-' && str[i+3] == '-'){ if(i > pv) CB_LISTPUSH(list, str + pv, i - pv); if((ep = strstr(str + i, "-->")) != NULL){ if(!cr) CB_LISTPUSH(list, str + i, ep - str - i + 3); i = ep - str + 2; pv = i + 1; } } else if(str[i+1] == '!' && str[i+2] == '[' && cbstrfwimatch(str + i, " pv) CB_LISTPUSH(list, str + pv, i - pv); if((ep = strstr(str + i, "]]>")) != NULL){ i += 9; CB_DATUMOPEN(datum); while(str + i < ep){ if(str[i] == '&'){ CB_DATUMCAT(datum, "&", 5); } else if(str[i] == '<'){ CB_DATUMCAT(datum, "<", 4); } else if(str[i] == '>'){ CB_DATUMCAT(datum, ">", 4); } else { CB_DATUMCAT(datum, str + i, 1); } i++; } if(CB_DATUMSIZE(datum) > 0) CB_LISTPUSH(list, CB_DATUMPTR(datum), CB_DATUMSIZE(datum)); CB_DATUMCLOSE(datum); i = ep - str + 2; pv = i + 1; } } else { if(i > pv) CB_LISTPUSH(list, str + pv, i - pv); tag = TRUE; pv = i; } } else if(tag && str[i] == '>'){ if(i > pv) CB_LISTPUSH(list, str + pv, i - pv + 1); tag = FALSE; pv = i + 1; } i++; } return list; } /* Get the map of attributes of a XML tag. */ CBMAP *cbxmlattrs(const char *str){ CBMAP *map; const unsigned char *rp, *key, *val; char *copy, *raw; int ksiz, vsiz; assert(str); map = cbmapopenex(CB_MAPPBNUM); rp = (unsigned char *)str; while(*rp == '<' || *rp == '/' || *rp == '?' || *rp == '!' || *rp == ' '){ rp++; } key = rp; while(*rp > 0x20 && *rp != '/' && *rp != '>'){ rp++; } cbmapput(map, "", -1, (char *)key, rp - key, FALSE); while(*rp != '\0'){ while(*rp != '\0' && (*rp <= 0x20 || *rp == '/' || *rp == '?' || *rp == '>')){ rp++; } key = rp; while(*rp > 0x20 && *rp != '/' && *rp != '>' && *rp != '='){ rp++; } ksiz = rp - key; while(*rp != '\0' && (*rp == '=' || *rp <= 0x20)){ rp++; } if(*rp == '"'){ rp++; val = rp; while(*rp != '\0' && *rp != '"'){ rp++; } vsiz = rp - val; } else if(*rp == '\''){ rp++; val = rp; while(*rp != '\0' && *rp != '\''){ rp++; } vsiz = rp - val; } else { val = rp; while(*rp > 0x20 && *rp != '"' && *rp != '\'' && *rp != '>'){ rp++; } vsiz = rp - val; } if(*rp != '\0') rp++; if(ksiz > 0){ CB_MEMDUP(copy, (char *)val, vsiz); raw = cbxmlunescape(copy); cbmapput(map, (char *)key, ksiz, raw, -1, FALSE); free(raw); free(copy); } } return map; } /* Escape a string with the meta characters of XML. */ char *cbxmlescape(const char *str){ CBDATUM *datum; assert(str); CB_DATUMOPEN(datum); while(*str != '\0'){ switch(*str){ case '&': CB_DATUMCAT(datum, "&", 5); break; case '<': CB_DATUMCAT(datum, "<", 4); break; case '>': CB_DATUMCAT(datum, ">", 4); break; case '"': CB_DATUMCAT(datum, """, 6); break; case '\'': CB_DATUMCAT(datum, "'", 6); break; default: CB_DATUMCAT(datum, str, 1); break; } str++; } return cbdatumtomalloc(datum, NULL); } /* Unescape a string with the entity references of XML. */ char *cbxmlunescape(const char *str){ CBDATUM *datum; assert(str); CB_DATUMOPEN(datum); while(*str != '\0'){ if(*str == '&'){ if(cbstrfwmatch(str, "&")){ CB_DATUMCAT(datum, "&", 1); str += 5; } else if(cbstrfwmatch(str, "<")){ CB_DATUMCAT(datum, "<", 1); str += 4; } else if(cbstrfwmatch(str, ">")){ CB_DATUMCAT(datum, ">", 1); str += 4; } else if(cbstrfwmatch(str, """)){ CB_DATUMCAT(datum, "\"", 1); str += 6; } else if(cbstrfwmatch(str, "'")){ CB_DATUMCAT(datum, "'", 1); str += 6; } else { CB_DATUMCAT(datum, str, 1); str++; } } else { CB_DATUMCAT(datum, str, 1); str++; } } return cbdatumtomalloc(datum, NULL); } /* Compress a serial object with ZLIB. */ char *cbdeflate(const char *ptr, int size, int *sp){ assert(ptr && sp); if(!_qdbm_deflate) return NULL; return _qdbm_deflate(ptr, size, sp, _QDBM_ZMZLIB); } /* Decompress a serial object compressed with ZLIB. */ char *cbinflate(const char *ptr, int size, int *sp){ assert(ptr && size >= 0); if(!_qdbm_inflate) return NULL; return _qdbm_inflate(ptr, size, sp, _QDBM_ZMZLIB); } /* Compress a serial object with GZIP. */ char *cbgzencode(const char *ptr, int size, int *sp){ assert(ptr && sp); if(!_qdbm_deflate) return NULL; return _qdbm_deflate(ptr, size, sp, _QDBM_ZMGZIP); } /* Decompress a serial object compressed with GZIP. */ char *cbgzdecode(const char *ptr, int size, int *sp){ assert(ptr && size >= 0); if(!_qdbm_inflate) return NULL; return _qdbm_inflate(ptr, size, sp, _QDBM_ZMGZIP); } /* Get the CRC32 checksum of a serial object. */ unsigned int cbgetcrc(const char *ptr, int size){ assert(ptr); if(!_qdbm_inflate) return 0; return _qdbm_getcrc(ptr, size); } /* Compress a serial object with LZO. */ char *cblzoencode(const char *ptr, int size, int *sp){ assert(ptr && sp); if(!_qdbm_lzoencode) return NULL; return _qdbm_lzoencode(ptr, size, sp); } /* Decompress a serial object compressed with LZO. */ char *cblzodecode(const char *ptr, int size, int *sp){ assert(ptr && size >= 0); if(!_qdbm_lzodecode) return NULL; return _qdbm_lzodecode(ptr, size, sp); } /* Compress a serial object with BZIP2. */ char *cbbzencode(const char *ptr, int size, int *sp){ assert(ptr && sp); if(!_qdbm_bzencode) return NULL; return _qdbm_bzencode(ptr, size, sp); } /* Decompress a serial object compressed with BZIP2. */ char *cbbzdecode(const char *ptr, int size, int *sp){ assert(ptr && size >= 0); if(!_qdbm_bzdecode) return NULL; return _qdbm_bzdecode(ptr, size, sp); } /* Convert the character encoding of a string. */ char *cbiconv(const char *ptr, int size, const char *icode, const char *ocode, int *sp, int *mp){ char *res; assert(ptr && icode && ocode); if(!_qdbm_iconv) return NULL; if((res = _qdbm_iconv(ptr, size, icode, ocode, sp, mp)) != NULL) return res; if(!cbstricmp(icode, ocode)){ if(sp) *sp = size; if(mp) *mp = 0; CB_MEMDUP(res, ptr, size < 0 ? strlen(ptr) : size); return res; } return NULL; } /* Detect the encoding of a string automatically. */ const char *cbencname(const char *ptr, int size){ assert(ptr); if(!_qdbm_encname) return "ISO-8859-1"; return _qdbm_encname(ptr, size); } /* Get the jet lag of the local time in seconds. */ int cbjetlag(void){ struct tm ts, *tp; time_t t, gt, lt; if((t = time(NULL)) < 0) return 0; if(!(tp = _qdbm_gmtime(&t, &ts))) return 0; if((gt = mktime(tp)) < 0) return 0; if(!(tp = _qdbm_localtime(&t, &ts))) return 0; if((lt = mktime(tp)) < 0) return 0; return lt - gt; } /* Get the Gregorian calendar of a time. */ void cbcalendar(time_t t, int jl, int *yearp, int *monp, int *dayp, int *hourp, int *minp, int *secp){ struct tm ts, *tp; if(t < 0) t = time(NULL); t += jl; if(!(tp = _qdbm_gmtime(&t, &ts))) return; if(yearp) *yearp = tp->tm_year + 1900; if(monp) *monp = tp->tm_mon + 1; if(dayp) *dayp = tp->tm_mday; if(hourp) *hourp = tp->tm_hour; if(minp) *minp = tp->tm_min; if(secp) *secp = tp->tm_sec; } /* Get the day of week of a date. */ int cbdayofweek(int year, int mon, int day){ if(mon < 3){ year--; mon += 12; } return (day + ((8 + (13 * mon)) / 5) + (year + (year / 4) - (year / 100) + (year / 400))) % 7; } /* Get the string for a date in W3CDTF. */ char *cbdatestrwww(time_t t, int jl){ char date[CB_DATEBUFSIZ], tzone[CB_DATEBUFSIZ], *rv; int year, mon, day, hour, min, sec; cbcalendar(t, jl, &year, &mon, &day, &hour, &min, &sec); jl /= 60; if(jl == 0){ sprintf(tzone, "Z"); } else if(jl < 0){ jl *= -1; sprintf(tzone, "-%02d:%02d", jl / 60, jl % 60); } else { sprintf(tzone, "+%02d:%02d", jl / 60, jl % 60); } sprintf(date, "%04d-%02d-%02dT%02d:%02d:%02d%s", year, mon, day, hour, min, sec, tzone); CB_MEMDUP(rv, date, strlen(date)); return rv; } /* Get the string for a date in RFC 1123 format. */ char *cbdatestrhttp(time_t t, int jl){ char date[CB_DATEBUFSIZ], *wp, *rv; int year, mon, day, hour, min, sec; cbcalendar(t, jl, &year, &mon, &day, &hour, &min, &sec); jl /= 60; wp = date; switch(cbdayofweek(year, mon, day)){ case 0: wp += sprintf(wp, "Sun, "); break; case 1: wp += sprintf(wp, "Mon, "); break; case 2: wp += sprintf(wp, "Tue, "); break; case 3: wp += sprintf(wp, "Wed, "); break; case 4: wp += sprintf(wp, "Thu, "); break; case 5: wp += sprintf(wp, "Fri, "); break; case 6: wp += sprintf(wp, "Sat, "); break; } wp += sprintf(wp, "%02d ", day); switch(mon){ case 1: wp += sprintf(wp, "Jan "); break; case 2: wp += sprintf(wp, "Feb "); break; case 3: wp += sprintf(wp, "Mar "); break; case 4: wp += sprintf(wp, "Apr "); break; case 5: wp += sprintf(wp, "May "); break; case 6: wp += sprintf(wp, "Jun "); break; case 7: wp += sprintf(wp, "Jul "); break; case 8: wp += sprintf(wp, "Aug "); break; case 9: wp += sprintf(wp, "Sep "); break; case 10: wp += sprintf(wp, "Oct "); break; case 11: wp += sprintf(wp, "Nov "); break; case 12: wp += sprintf(wp, "Dec "); break; } wp += sprintf(wp, "%04d %02d:%02d:%02d ", year, hour, min, sec); if(jl == 0){ wp += sprintf(wp, "GMT"); } else if(jl < 0){ jl *= -1; wp += sprintf(wp, "-%02d%02d", jl / 60, jl % 60); } else { wp += sprintf(wp, "+%02d%02d", jl / 60, jl % 60); } CB_MEMDUP(rv, date, strlen(date)); return rv; } /* Get the time value of a date string in decimal, W3CDTF, or RFC 1123. */ time_t cbstrmktime(const char *str){ const char *crp; char *pv, *rp; int len, clen; time_t t; struct tm ts; assert(str); while(*str > '\0' && *str <= ' '){ str++; } if(*str == '\0') return -1; if(str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) return (time_t)strtol(str + 2, NULL, 16); memset(&ts, 0, sizeof(struct tm)); ts.tm_year = 70; ts.tm_mon = 0; ts.tm_mday = 1; ts.tm_hour = 0; ts.tm_min = 0; ts.tm_sec = 0; ts.tm_isdst = 0; len = strlen(str); t = (time_t)strtol(str, &pv, 10); if(*(signed char *)pv >= '\0' && *pv <= ' '){ while(*pv > '\0' && *pv <= ' '){ pv++; } if(*pv == '\0') return t; } if((pv[0] == 's' || pv[0] == 'S') && ((signed char *)pv)[1] >= '\0' && pv[1] <= ' ') return t; if((pv[0] == 'm' || pv[0] == 'M') && ((signed char *)pv)[1] >= '\0' && pv[1] <= ' ') return t * 60; if((pv[0] == 'h' || pv[0] == 'H') && ((signed char *)pv)[1] >= '\0' && pv[1] <= ' ') return t * 60 * 60; if((pv[0] == 'd' || pv[0] == 'D') && ((signed char *)pv)[1] >= '\0' && pv[1] <= ' ') return t * 60 * 60 * 24; if(len > 4 && str[4] == '-'){ ts.tm_year = atoi(str) - 1900; if((pv = strchr(str, '-')) != NULL && pv - str == 4){ rp = pv + 1; ts.tm_mon = atoi(rp) - 1; if((pv = strchr(rp, '-')) != NULL && pv - str == 7){ rp = pv + 1; ts.tm_mday = atoi(rp); if((pv = strchr(rp, 'T')) != NULL && pv - str == 10){ rp = pv + 1; ts.tm_hour = atoi(rp); if((pv = strchr(rp, ':')) != NULL && pv - str == 13){ rp = pv + 1; ts.tm_min = atoi(rp); } if((pv = strchr(rp, ':')) != NULL && pv - str == 16){ rp = pv + 1; ts.tm_sec = atoi(rp); } if((pv = strchr(rp, '.')) != NULL && pv - str >= 19) rp = pv + 1; strtol(rp, &pv, 10); if((*pv == '+' || *pv == '-') && strlen(pv) >= 6 && pv[3] == ':') ts.tm_sec -= (atoi(pv + 1) * 3600 + atoi(pv + 4) * 60) * (pv[0] == '+' ? 1 : -1); } } } ts.tm_sec += cbjetlag(); return mktime(&ts); } if(len > 4 && str[4] == '/'){ ts.tm_year = atoi(str) - 1900; if((pv = strchr(str, '/')) != NULL && pv - str == 4){ rp = pv + 1; ts.tm_mon = atoi(rp) - 1; if((pv = strchr(rp, '/')) != NULL && pv - str == 7){ rp = pv + 1; ts.tm_mday = atoi(rp); if((pv = strchr(rp, ' ')) != NULL && pv - str == 10){ rp = pv + 1; ts.tm_hour = atoi(rp); if((pv = strchr(rp, ':')) != NULL && pv - str == 13){ rp = pv + 1; ts.tm_min = atoi(rp); } if((pv = strchr(rp, ':')) != NULL && pv - str == 16){ rp = pv + 1; ts.tm_sec = atoi(rp); } if((pv = strchr(rp, '.')) != NULL && pv - str >= 19) rp = pv + 1; strtol(rp, &pv, 10); if((*pv == '+' || *pv == '-') && strlen(pv) >= 6 && pv[3] == ':') ts.tm_sec -= (atoi(pv + 1) * 3600 + atoi(pv + 4) * 60) * (pv[0] == '+' ? 1 : -1); } } } ts.tm_sec += cbjetlag(); return mktime(&ts); } crp = str; if(len >= 4 && str[3] == ',') crp = str + 4; while(*crp == ' '){ crp++; } ts.tm_mday = atoi(crp); while((*crp >= '0' && *crp <= '9') || *crp == ' '){ crp++; } if(cbstrfwimatch(crp, "Jan")){ ts.tm_mon = 0; } else if(cbstrfwimatch(crp, "Feb")){ ts.tm_mon = 1; } else if(cbstrfwimatch(crp, "Mar")){ ts.tm_mon = 2; } else if(cbstrfwimatch(crp, "Apr")){ ts.tm_mon = 3; } else if(cbstrfwimatch(crp, "May")){ ts.tm_mon = 4; } else if(cbstrfwimatch(crp, "Jun")){ ts.tm_mon = 5; } else if(cbstrfwimatch(crp, "Jul")){ ts.tm_mon = 6; } else if(cbstrfwimatch(crp, "Aug")){ ts.tm_mon = 7; } else if(cbstrfwimatch(crp, "Sep")){ ts.tm_mon = 8; } else if(cbstrfwimatch(crp, "Oct")){ ts.tm_mon = 9; } else if(cbstrfwimatch(crp, "Nov")){ ts.tm_mon = 10; } else if(cbstrfwimatch(crp, "Dec")){ ts.tm_mon = 11; } else { ts.tm_mon = -1; } if(ts.tm_mon >= 0) crp += 3; while(*crp == ' '){ crp++; } ts.tm_year = atoi(crp); if(ts.tm_year >= 1969) ts.tm_year -= 1900; while(*crp >= '0' && *crp <= '9'){ crp++; } while(*crp == ' '){ crp++; } if(ts.tm_mday > 0 && ts.tm_mon >= 0 && ts.tm_year >= 0){ clen = strlen(crp); if(clen >= 8 && crp[2] == ':' && crp[5] == ':'){ ts.tm_hour = atoi(crp + 0); ts.tm_min = atoi(crp + 3); ts.tm_sec = atoi(crp + 6); if(clen >= 14 && crp[8] == ' ' && (crp[9] == '+' || crp[9] == '-')){ ts.tm_sec -= ((crp[10] - '0') * 36000 + (crp[11] - '0') * 3600 + (crp[12] - '0') * 600 + (crp[13] - '0') * 60) * (crp[9] == '+' ? 1 : -1); } else if(clen > 9){ if(!strcmp(crp + 9, "JST")){ ts.tm_sec -= 9 * 3600; } else if(!strcmp(crp + 9, "CCT")){ ts.tm_sec -= 8 * 3600; } else if(!strcmp(crp + 9, "KST")){ ts.tm_sec -= 9 * 3600; } else if(!strcmp(crp + 9, "EDT")){ ts.tm_sec -= -4 * 3600; } else if(!strcmp(crp + 9, "EST")){ ts.tm_sec -= -5 * 3600; } else if(!strcmp(crp + 9, "CDT")){ ts.tm_sec -= -5 * 3600; } else if(!strcmp(crp + 9, "CST")){ ts.tm_sec -= -6 * 3600; } else if(!strcmp(crp + 9, "MDT")){ ts.tm_sec -= -6 * 3600; } else if(!strcmp(crp + 9, "MST")){ ts.tm_sec -= -7 * 3600; } else if(!strcmp(crp + 9, "PDT")){ ts.tm_sec -= -7 * 3600; } else if(!strcmp(crp + 9, "PST")){ ts.tm_sec -= -8 * 3600; } else if(!strcmp(crp + 9, "HDT")){ ts.tm_sec -= -9 * 3600; } else if(!strcmp(crp + 9, "HST")){ ts.tm_sec -= -10 * 3600; } } } ts.tm_sec += cbjetlag(); return mktime(&ts); } return -1; } /* Get user and system processing times. */ void cbproctime(double *usrp, double *sysp){ struct tms buf; times(&buf); if(usrp) *usrp = (double)buf.tms_utime / sysconf(_SC_CLK_TCK); if(sysp) *sysp = (double)buf.tms_stime / sysconf(_SC_CLK_TCK); } /* Ensure that the standard I/O is binary mode. */ void cbstdiobin(void){ if(setmode(0, O_BINARY) == -1 || setmode(1, O_BINARY) == -1 || setmode(2, O_BINARY) == -1) cbmyfatal("setmode failed"); } /************************************************************************************************* * features for experts *************************************************************************************************/ /* Show error message on the standard error output and exit. */ void *cbmyfatal(const char *message){ char buf[CB_MSGBUFSIZ]; assert(message); if(cbfatalfunc){ cbfatalfunc(message); } else { sprintf(buf, "fatal error: %s\n", message); write(2, buf, strlen(buf)); } exit(1); return NULL; } /* Create a datum handle from an allocated region. */ CBDATUM *cbdatumopenbuf(char *ptr, int size){ CBDATUM *datum; assert(ptr && size >= 0); CB_REALLOC(ptr, size + 1); CB_MALLOC(datum, sizeof(*datum)); datum->dptr = ptr; datum->dptr[size] = '\0'; datum->dsize = size; datum->asize = size; return datum; } /* Set a buffer to a datum handle. */ void cbdatumsetbuf(CBDATUM *datum, char *ptr, int size){ assert(datum && ptr && size >= 0); free(datum->dptr); CB_REALLOC(ptr, size + 1); datum->dptr = ptr; datum->dptr[size] = '\0'; datum->dsize = size; datum->asize = size; } /* Add an allocated element at the end of a list. */ void cblistpushbuf(CBLIST *list, char *ptr, int size){ int index; assert(list && ptr && size >= 0); index = list->start + list->num; if(index >= list->anum){ list->anum *= 2; CB_REALLOC(list->array, list->anum * sizeof(list->array[0])); } list->array[index].dptr = ptr; list->array[index].dsize = size; list->num++; } /* Get a map handle with specifying the number of buckets. */ CBMAP *cbmapopenex(int bnum){ CBMAP *map; int i; assert(bnum > 0); CB_MALLOC(map, sizeof(*map)); CB_MALLOC(map->buckets, sizeof(map->buckets[0]) * bnum); for(i = 0; i < bnum; i++){ map->buckets[i] = NULL; } map->first = NULL; map->last = NULL; map->cur = NULL; map->bnum = bnum; map->rnum = 0; return map; } /************************************************************************************************* * private objects *************************************************************************************************/ /* Handler to invoke the global garbage collector. */ static void cbggchandler(void){ cbggckeeper(NULL, NULL); } /* Manage resources of the global garbage collector. `ptr' specifies the pointer to add to the collection. If it is `NULL', all resources are released. `func' specifies the pointer to the function to release the resources. */ static void cbggckeeper(void *ptr, void (*func)(void *)){ static void **parray = NULL; static void (**farray)(void *) = NULL; static int onum = 0; static int asiz = CB_GCUNIT; int i; if(!ptr){ if(!parray) return; for(i = onum - 1; i >= 0; i--){ farray[i](parray[i]); } free(parray); free(farray); parray = NULL; farray = NULL; onum = 0; asiz = CB_GCUNIT; return; } if(!parray){ CB_MALLOC(parray, sizeof(void *) * asiz); CB_MALLOC(farray, sizeof(void *) * asiz); if(atexit(cbggchandler) != 0) cbmyfatal("gc failed"); } if(onum >= asiz){ asiz *= 2; CB_REALLOC(parray, sizeof(void *) * asiz); CB_REALLOC(farray, sizeof(void *) * asiz); } parray[onum] = ptr; farray[onum] = func; onum++; } /* Utility function for quick sort. `bp' specifies the pointer to the pointer to an array. `nmemb' specifies the number of elements of the array. `size' specifies the size of each element. `pswap' specifies the pointer to the swap region for a pivot. `vswap' specifies the pointer to the swap region for elements. `compar' specifies the pointer to comparing function. */ static void cbqsortsub(char *bp, int nmemb, int size, char *pswap, char *vswap, int(*compar)(const void *, const void *)){ int top, bottom; assert(bp && nmemb >= 0 && size > 0 && pswap && vswap && compar); if(nmemb < 10){ if(nmemb > 1) cbisort(bp, nmemb, size, compar); return; } top = 0; bottom = nmemb - 1; memcpy(pswap, bp + (nmemb / 2) * size, size); while(top - 1 < bottom){ if(compar(bp + top * size, pswap) < 0){ top++; } else if(compar(bp + bottom * size, pswap) > 0){ bottom--; } else { if(top != bottom){ memcpy(vswap, bp + top * size, size); memcpy(bp + top * size, bp + bottom * size, size); memcpy(bp + bottom * size, vswap, size); } top++; bottom--; } } cbqsortsub(bp, top, size, pswap, vswap, compar); cbqsortsub(bp + (bottom + 1) * size, nmemb - bottom - 1, size, pswap, vswap, compar); } /* Compare two list elements. `a' specifies the pointer to one element. `b' specifies the pointer to the other element. The return value is positive if a is big, negative if b is big, else, it is 0. */ static int cblistelemcmp(const void *a, const void *b){ int i, size; CBLISTDATUM *ap, *bp; char *ao, *bo; assert(a && b); ap = (CBLISTDATUM *)a; bp = (CBLISTDATUM *)b; ao = ap->dptr; bo = bp->dptr; size = ap->dsize < bp->dsize ? ap->dsize : bp->dsize; for(i = 0; i < size; i++){ if(ao[i] > bo[i]) return 1; if(ao[i] < bo[i]) return -1; } return ap->dsize - bp->dsize; } /* Compare two keys. `abuf' specifies the pointer to the region of the former. `asiz' specifies the size of the region. `bbuf' specifies the pointer to the region of the latter. `bsiz' specifies the size of the region. The return value is 0 if two equals, positive if the formar is big, else, negative. */ static int cbkeycmp(const char *abuf, int asiz, const char *bbuf, int bsiz){ assert(abuf && asiz >= 0 && bbuf && bsiz >= 0); if(asiz > bsiz) return 1; if(asiz < bsiz) return -1; return memcmp(abuf, bbuf, asiz); } /* END OF FILE */ qdbm-1.8.78/configure0000755000175000017500000035464111426320050013461 0ustar mikiomikio#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.65 for qdbm 1.8.78. # # # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, # 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, # Inc. # # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi " as_required="as_fn_return () { (exit \$1); } as_fn_success () { as_fn_return 0; } as_fn_failure () { as_fn_return 1; } as_fn_ret_success () { return 0; } as_fn_ret_failure () { return 1; } exitcode=0 as_fn_success || { exitcode=1; echo as_fn_success failed.; } as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : else exitcode=1; echo positional parameters were not saved. fi test x\$exitcode = x0 || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1" if (eval "$as_required") 2>/dev/null; then : as_have_required=yes else as_have_required=no fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. as_shell=$as_dir/$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : CONFIG_SHELL=$as_shell as_have_required=yes if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : break 2 fi fi done;; esac as_found=false done $as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : CONFIG_SHELL=$SHELL as_have_required=yes fi; } IFS=$as_save_IFS if test "x$CONFIG_SHELL" != x; then : # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV export CONFIG_SHELL exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"} fi if test x$as_have_required = xno; then : $as_echo "$0: This script requires a shell more modern than all" $as_echo "$0: the shells that I found on your system." if test x${ZSH_VERSION+set} = xset ; then $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" $as_echo "$0: be upgraded to zsh 4.3.4 or later." else $as_echo "$0: Please tell bug-autoconf@gnu.org about your system, $0: including any error possibly output before this $0: message. Then install a modern shell, or manually run $0: the script under such a shell if you do have one." fi exit 1 fi fi fi SHELL=${CONFIG_SHELL-/bin/sh} export SHELL # Unset more variables known to interfere with behavior of common tools. CLICOLOR_FORCE= GREP_OPTIONS= unset CLICOLOR_FORCE GREP_OPTIONS ## --------------------- ## ## M4sh Shell Functions. ## ## --------------------- ## # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error "cannot create directory $as_dir" } # as_fn_mkdir_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith # as_fn_error ERROR [LINENO LOG_FD] # --------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with status $?, using 1 if that was 0. as_fn_error () { as_status=$?; test $as_status -eq 0 && as_status=1 if test "$3"; then as_lineno=${as_lineno-"$2"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $1" >&$3 fi $as_echo "$as_me: error: $1" >&2 as_fn_exit $as_status } # as_fn_error if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits as_lineno_1=$LINENO as_lineno_1a=$LINENO as_lineno_2=$LINENO as_lineno_2a=$LINENO eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -p'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -p' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -p' fi else as_ln_s='cp -p' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi if test -x / >/dev/null 2>&1; then as_test_x='test -x' else if ls -dL / >/dev/null 2>&1; then as_ls_L_option=L else as_ls_L_option= fi as_test_x=' eval sh -c '\'' if test -d "$1"; then test -d "$1/."; else case $1 in #( -*)set "./$1";; esac; case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( ???[sx]*):;;*)false;;esac;fi '\'' sh ' fi as_executable_p=$as_test_x # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME='qdbm' PACKAGE_TARNAME='qdbm' PACKAGE_VERSION='1.8.78' PACKAGE_STRING='qdbm 1.8.78' PACKAGE_BUGREPORT='' PACKAGE_URL='' ac_subst_vars='LTLIBOBJS LIBOBJS AR LD MGWLIBS MYOPTS MYDEFS TARGETS LIBREV LIBVER OBJEXT EXEEXT ac_ct_CC CPPFLAGS LDFLAGS CFLAGS CC target_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_URL PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL' ac_subst_files='' ac_user_opts=' enable_option_checking enable_debug enable_devel enable_stable enable_pthread enable_lock enable_mmap enable_zlib enable_lzo enable_bzip enable_iconv enable_warn ' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS' # Initialize some variables set by options. ac_init_help= ac_init_version=false ac_unrecognized_opts= ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) as_fn_error "unrecognized option: \`$ac_option' Try \`$0 --help' for more information." ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) as_fn_error "invalid variable name: \`$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` as_fn_error "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) as_fn_error "unrecognized options: $ac_unrecognized_opts" ;; *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi # Check all directory arguments for consistency. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir do eval ac_val=\$$ac_var # Remove trailing slashes. case $ac_val in */ ) ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` eval $ac_var=\$ac_val;; esac # Be sure to have absolute directory names. case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac as_fn_error "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe $as_echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. If a cross compiler is detected then cross compile mode will be used." >&2 elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || as_fn_error "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || as_fn_error "pwd does not report name of working directory" # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." as_fn_error "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures qdbm 1.8.78 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/qdbm] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of qdbm 1.8.78:";; esac cat <<\_ACEOF Optional Features: --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --enable-debug build for debugging --enable-devel build for development --enable-stable build for stable release --enable-pthread use POSIX thread and make APIs thread-safe --disable-lock build for environments without file locking --disable-mmap build for environments without memory mapping --enable-zlib feature ZLIB for B+ tree and inverted index --enable-lzo feature LZO for B+ tree and inverted index --enable-bzip feature BZIP2 for B+ tree and inverted index --enable-iconv feature ICONV utilities --disable-warn hide warnings in the configuration Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to the package provider. _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for guested configure. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF qdbm configure 1.8.78 generated by GNU Autoconf 2.65 Copyright (C) 2009 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi ## ------------------------ ## ## Autoconf initialization. ## ## ------------------------ ## # ac_fn_c_try_compile LINENO # -------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} as_fn_set_status $ac_retval } # ac_fn_c_try_compile # ac_fn_c_try_link LINENO # ----------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} as_fn_set_status $ac_retval } # ac_fn_c_try_link cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by qdbm $as_me 1.8.78, which was generated by GNU Autoconf 2.65. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. $as_echo "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) as_fn_append ac_configure_args1 " '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done { ac_configure_args0=; unset ac_configure_args0;} { ac_configure_args1=; unset ac_configure_args1;} # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo cat <<\_ASBOX ## ---------------- ## ## Cache variables. ## ## ---------------- ## _ASBOX echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo cat <<\_ASBOX ## ----------------- ## ## Output variables. ## ## ----------------- ## _ASBOX echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then cat <<\_ASBOX ## ------------------- ## ## File substitutions. ## ## ------------------- ## _ASBOX echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then cat <<\_ASBOX ## ----------- ## ## confdefs.h. ## ## ----------- ## _ASBOX echo cat confdefs.h echo fi test "$ac_signal" != 0 && $as_echo "$as_me: caught signal $ac_signal" $as_echo "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h $as_echo "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_URL "$PACKAGE_URL" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. ac_site_file1=NONE ac_site_file2=NONE if test -n "$CONFIG_SITE"; then ac_site_file1=$CONFIG_SITE elif test "x$prefix" != xNONE; then ac_site_file1=$prefix/share/config.site ac_site_file2=$prefix/etc/config.site else ac_site_file1=$ac_default_prefix/share/config.site ac_site_file2=$ac_default_prefix/etc/config.site fi for ac_site_file in "$ac_site_file1" "$ac_site_file2" do test "x$ac_site_file" = xNONE && continue if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 $as_echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 $as_echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 $as_echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then # differences in whitespace do not lead to failure. ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 $as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 $as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 $as_echo "$as_me: former value: \`$ac_old_val'" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 $as_echo "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 $as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} as_fn_error "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## ## -------------------- ## ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu # Export variables LIBVER=14 LIBREV=14 TARGETS="all" MYDEFS="" MYOPTS="" MGWLIBS="" LD="ld" AR="ar" # Building paths pathtmp="$PATH" PATH="$HOME/bin:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin" PATH="$PATH:/usr/ccs/bin:/usr/ucb:/usr/xpg4/bin:/usr/xpg6/bin:$pathtmp" LIBRARY_PATH="$HOME/lib:/usr/local/lib:$LIBRARY_PATH" LD_LIBRARY_PATH="$HOME/lib:/usr/local/lib:$LD_LIBRARY_PATH" CPATH="$HOME/include:/usr/local/include:$CPATH" export PATH LIBRARY_PATH LD_LIBRARY_PATH CPATH #================================================================ # Options #================================================================ # Internal variables enables="" ispthread="" iszlib="" isiconv="" isnowarn="" # Debug mode # Check whether --enable-debug was given. if test "${enable_debug+set}" = set; then : enableval=$enable_debug; fi if test "$enable_debug" = "yes" then TARGETS="debug" enables="$enables (debug)" fi # Developping mode # Check whether --enable-devel was given. if test "${enable_devel+set}" = set; then : enableval=$enable_devel; fi if test "$enable_devel" = "yes" then TARGETS="devel" enables="$enables (devel)" fi # Stable mode # Check whether --enable-stable was given. if test "${enable_stable+set}" = set; then : enableval=$enable_stable; fi if test "$enable_stable" = "yes" then TARGETS="stable" enables="$enables (stable)" fi # Enable POSIX thread # Check whether --enable-pthread was given. if test "${enable_pthread+set}" = set; then : enableval=$enable_pthread; fi if test "$enable_pthread" = "yes" then MYDEFS="$MYDEFS -DMYPTHREAD" enables="$enables (pthread)" ispthread="yes" fi # Disable file locking # Check whether --enable-lock was given. if test "${enable_lock+set}" = set; then : enableval=$enable_lock; fi if test "$enable_lock" = "no" then MYDEFS="$MYDEFS -DMYNOLOCK" enables="$enables (no-lock)" fi # Disable memory mapping # Check whether --enable-mmap was given. if test "${enable_mmap+set}" = set; then : enableval=$enable_mmap; fi if test "$enable_mmap" = "no" then MYDEFS="$MYDEFS -DMYNOMMAP" enables="$enables (no-mmap)" fi # Enable ZLIB compression # Check whether --enable-zlib was given. if test "${enable_zlib+set}" = set; then : enableval=$enable_zlib; fi if test "$enable_zlib" = "yes" then MYDEFS="$MYDEFS -DMYZLIB" MGWLIBS="-lz $MGWLIBS" enables="$enables (zlib)" iszlib="yes" fi # Enable LZO compression # Check whether --enable-lzo was given. if test "${enable_lzo+set}" = set; then : enableval=$enable_lzo; fi if test "$enable_lzo" = "yes" then MYDEFS="$MYDEFS -DMYLZO" MGWLIBS="-llzo2 $MGWLIBS" enables="$enables (lzo)" islzo="yes" fi # Enable BZIP2 compression # Check whether --enable-bzip was given. if test "${enable_bzip+set}" = set; then : enableval=$enable_bzip; fi if test "$enable_bzip" = "yes" then MYDEFS="$MYDEFS -DMYBZIP" MGWLIBS="-lbz2 $MGWLIBS" enables="$enables (bzip)" isbzip="yes" fi # Enable ICONV utilities # Check whether --enable-iconv was given. if test "${enable_iconv+set}" = set; then : enableval=$enable_iconv; fi if test "$enable_iconv" = "yes" then MYDEFS="$MYDEFS -DMYICONV" MGWLIBS="-liconv $MGWLIBS" enables="$enables (iconv)" isiconv="yes" fi # No warning configuration # Check whether --enable-warn was given. if test "${enable_warn+set}" = set; then : enableval=$enable_warn; fi if test "$enable_warn" = "no" then isnowarn="yes" fi # Messages printf '#================================================================\n' printf '# Configuring QDBM version %s%s.\n' "$PACKAGE_VERSION" "$enables" printf '#================================================================\n' #================================================================ # Checking Commands to Build with #================================================================ # C compiler ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_CC+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_ac_ct_CC+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_CC+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_CC+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_CC+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_ac_ct_CC+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error "no acceptable C compiler found in \$PATH See \`config.log' for more details." "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 $as_echo_n "checking whether the C compiler works... " >&6; } ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # The possible output files: ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { { ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link_default") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an `-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else ac_file='' fi if test -z "$ac_file"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { as_fn_set_status 77 as_fn_error "C compiler cannot create executables See \`config.log' for more details." "$LINENO" 5; }; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 $as_echo_n "checking for C compiler default output file name... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 $as_echo "$ac_file" >&6; } ac_exeext=$ac_cv_exeext rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 $as_echo_n "checking for suffix of executables... " >&6; } if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error "cannot compute suffix of executables: cannot compile and link See \`config.log' for more details." "$LINENO" 5; } fi rm -f conftest conftest$ac_cv_exeext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 $as_echo "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { FILE *f = fopen ("conftest.out", "w"); return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF ac_clean_files="$ac_clean_files conftest.out" # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 $as_echo_n "checking whether we are cross compiling... " >&6; } if test "$cross_compiling" != yes; then { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if { ac_try='./conftest$ac_cv_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error "cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details." "$LINENO" 5; } fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 $as_echo "$cross_compiling" >&6; } rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 $as_echo_n "checking for suffix of object files... " >&6; } if test "${ac_cv_objext+set}" = set; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error "cannot compute suffix of object files: cannot compile See \`config.log' for more details." "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 $as_echo "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if test "${ac_cv_c_compiler_gnu+set}" = set; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if test "${ac_cv_prog_cc_g+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if test "${ac_cv_prog_cc_c89+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test "$GCC" != "yes" then if test "$isnowarn" != "yes" then printf '#================================================================\n' 1>&2 printf '# WARNING: GCC is required to build this package.\n' 1>&2 printf '#================================================================\n' 1>&2 fi fi if uname | egrep -i 'Linux' > /dev/null 2>&1 && uname -m | egrep '(x|i)(3|4|5|6|7|8|9)?86' > /dev/null 2>&1 then MYOPTS="-minline-all-stringops" fi if uname | egrep -i 'SunOS' > /dev/null 2>&1 then MYOPTS="-O1 -fno-omit-frame-pointer -fno-force-addr" fi if uname | egrep -i 'BSD' > /dev/null 2>&1 then MYOPTS="-O1 -fno-omit-frame-pointer -fno-force-addr" fi if gcc --version | egrep -i '^2\.(8|9)' > /dev/null 2>&1 then MYOPTS="-O1 -fno-omit-frame-pointer -fno-force-addr" fi # Linker printf 'checking for ld... ' if which ld | grep '/ld$' > /dev/null 2>&1 then LD=`which ld` printf '%s\n' "$LD" else printf 'no\n' if test "$isnowarn" != "yes" then printf '#================================================================\n' 1>&2 printf '# WARNING: ld is not found in PATH.\n' 1>&2 printf '#================================================================\n' 1>&2 fi fi # Archiver printf 'checking for ar... ' if which ar | grep '/ar$' > /dev/null 2>&1 then AR=`which ar` printf '%s\n' "$AR" else printf 'no\n' if test "$isnowarn" != "yes" then printf '#================================================================\n' 1>&2 printf '# WARNING: ar is not found in PATH.\n' 1>&2 printf '#================================================================\n' 1>&2 fi fi #================================================================ # Checking Libraries #================================================================ # Underlying libraries { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lc" >&5 $as_echo_n "checking for main in -lc... " >&6; } if test "${ac_cv_lib_c_main+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lc $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_c_main=yes else ac_cv_lib_c_main=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_c_main" >&5 $as_echo "$ac_cv_lib_c_main" >&6; } if test "x$ac_cv_lib_c_main" = x""yes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBC 1 _ACEOF LIBS="-lc $LIBS" fi # for pthread if test "$ispthread" = "yes" then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lpthread" >&5 $as_echo_n "checking for main in -lpthread... " >&6; } if test "${ac_cv_lib_pthread_main+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lpthread $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_pthread_main=yes else ac_cv_lib_pthread_main=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_main" >&5 $as_echo "$ac_cv_lib_pthread_main" >&6; } if test "x$ac_cv_lib_pthread_main" = x""yes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBPTHREAD 1 _ACEOF LIBS="-lpthread $LIBS" fi fi # for zlib if test "$iszlib" = "yes" then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lz" >&5 $as_echo_n "checking for main in -lz... " >&6; } if test "${ac_cv_lib_z_main+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lz $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_z_main=yes else ac_cv_lib_z_main=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_z_main" >&5 $as_echo "$ac_cv_lib_z_main" >&6; } if test "x$ac_cv_lib_z_main" = x""yes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBZ 1 _ACEOF LIBS="-lz $LIBS" fi fi # for lzo if test "$islzo" = "yes" then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -llzo2" >&5 $as_echo_n "checking for main in -llzo2... " >&6; } if test "${ac_cv_lib_lzo2_main+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-llzo2 $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_lzo2_main=yes else ac_cv_lib_lzo2_main=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_lzo2_main" >&5 $as_echo "$ac_cv_lib_lzo2_main" >&6; } if test "x$ac_cv_lib_lzo2_main" = x""yes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBLZO2 1 _ACEOF LIBS="-llzo2 $LIBS" fi fi # for bzip if test "$isbzip" = "yes" then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lbz2" >&5 $as_echo_n "checking for main in -lbz2... " >&6; } if test "${ac_cv_lib_bz2_main+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lbz2 $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_bz2_main=yes else ac_cv_lib_bz2_main=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_bz2_main" >&5 $as_echo "$ac_cv_lib_bz2_main" >&6; } if test "x$ac_cv_lib_bz2_main" = x""yes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBBZ2 1 _ACEOF LIBS="-lbz2 $LIBS" fi fi # for iconv if test "$isiconv" = "yes" then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -liconv" >&5 $as_echo_n "checking for main in -liconv... " >&6; } if test "${ac_cv_lib_iconv_main+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-liconv $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_iconv_main=yes else ac_cv_lib_iconv_main=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_iconv_main" >&5 $as_echo "$ac_cv_lib_iconv_main" >&6; } if test "x$ac_cv_lib_iconv_main" = x""yes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBICONV 1 _ACEOF LIBS="-liconv $LIBS" fi fi # For old BSDs if test "$ispthread" = "yes" && uname -a | grep BSD > /dev/null && test -f /usr/lib/libc_r.a && test ! -f /usr/lib/libpthread.a then LIBS=`printf '%s' "$LIBS" | sed 's/-lc/-lc_r/g'` fi # Duplication of QDBM for C { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lqdbm" >&5 $as_echo_n "checking for main in -lqdbm... " >&6; } if test "${ac_cv_lib_qdbm_main+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lqdbm $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_qdbm_main=yes else ac_cv_lib_qdbm_main=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_qdbm_main" >&5 $as_echo "$ac_cv_lib_qdbm_main" >&6; } if test "x$ac_cv_lib_qdbm_main" = x""yes; then : if test "$isnowarn" != "yes" then printf '#================================================================\n' 1>&2 printf '# WARNING: The existing library was detected.\n' 1>&2 printf '#================================================================\n' 1>&2 fi fi #================================================================ # Generic Settings #================================================================ # Export variables # Targets ac_config_files="$ac_config_files Makefile LTmakefile qdbm.spec qdbm.pc" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then test "x$cache_file" != "x/dev/null" && { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} cat confcache >$cache_file else { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' # Transform confdefs.h into DEFS. # Protect against shell expansion while executing Makefile rules. # Protect against Makefile macro expansion. # # If the first sed substitution is executed (which looks for macros that # take arguments), then branch to the quote section. Otherwise, # look for a macro that doesn't take arguments. ac_script=' :mline /\\$/{ N s,\\\n,, b mline } t clear :clear s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g t quote s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g t quote b any :quote s/[ `~#$^&*(){}\\|;'\''"<>?]/\\&/g s/\[/\\&/g s/\]/\\&/g s/\$/$$/g H :any ${ g s/^\n// s/\n/ /g p } ' DEFS=`sed -n "$ac_script" confdefs.h` ac_libobjs= ac_ltlibobjs= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`$as_echo "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs : ${CONFIG_STATUS=./config.status} ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 $as_echo "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # as_fn_error ERROR [LINENO LOG_FD] # --------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with status $?, using 1 if that was 0. as_fn_error () { as_status=$?; test $as_status -eq 0 && as_status=1 if test "$3"; then as_lineno=${as_lineno-"$2"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $1" >&$3 fi $as_echo "$as_me: error: $1" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -p'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -p' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -p' fi else as_ln_s='cp -p' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi if test -x / >/dev/null 2>&1; then as_test_x='test -x' else if ls -dL / >/dev/null 2>&1; then as_ls_L_option=L else as_ls_L_option= fi as_test_x=' eval sh -c '\'' if test -d "$1"; then test -d "$1/."; else case $1 in #( -*)set "./$1";; esac; case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( ???[sx]*):;;*)false;;esac;fi '\'' sh ' fi as_executable_p=$as_test_x # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 ## ----------------------------------- ## ## Main body of $CONFIG_STATUS script. ## ## ----------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by qdbm $as_me 1.8.78, which was generated by GNU Autoconf 2.65. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ \`$as_me' instantiates files and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit --config print configuration, then exit -q, --quiet, --silent do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE Configuration files: $config_files Report bugs to the package provider." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ qdbm config.status 1.8.78 configured by $0, generated by GNU Autoconf 2.65, with options \\"\$ac_cs_config\\" Copyright (C) 2009 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) $as_echo "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) $as_echo "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --he | --h | --help | --hel | -h ) $as_echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) as_fn_error "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX $as_echo "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; "LTmakefile") CONFIG_FILES="$CONFIG_FILES LTmakefile" ;; "qdbm.spec") CONFIG_FILES="$CONFIG_FILES qdbm.spec" ;; "qdbm.pc") CONFIG_FILES="$CONFIG_FILES qdbm.pc" ;; *) as_fn_error "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= trap 'exit_status=$? { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error "cannot create a temporary directory in ." "$LINENO" 5 # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with `./config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=`echo X | tr X '\015'` # On cygwin, bash can eat \r inside `` if the user requested igncr. # But we know of no other shell where ac_cr would be empty at this # point, so we can use a bashism as a fallback. if test "x$ac_cr" = x; then eval ac_cr=\$\'\\r\' fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_num=`echo "$ac_subst_vars" | grep -c '$'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>"\$tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\)..*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\)..*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' >$CONFIG_STATUS || ac_write_fail=1 rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$tmp/subs1.awk" > "$tmp/subs.awk" \ || as_fn_error "could not setup config files machinery" "$LINENO" 5 _ACEOF # VPATH may cause trouble with some makes, so we remove $(srcdir), # ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=/{ s/:*\$(srcdir):*/:/ s/:*\${srcdir}:*/:/ s/:*@srcdir@:*/:/ s/^\([^=]*=[ ]*\):*/\1/ s/:*$// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" eval set X " :F $CONFIG_FILES " shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) as_fn_error "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || as_fn_error "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 $as_echo "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`$as_echo "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$tmp/stdin" \ || as_fn_error "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 $as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$tmp/subs.awk" >$tmp/out \ || as_fn_error "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } && { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined." >&5 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined." >&2;} rm -f "$tmp/stdin" case $ac_file in -) cat "$tmp/out" && rm -f "$tmp/out";; *) rm -f "$ac_file" && mv "$tmp/out" "$ac_file";; esac \ || as_fn_error "could not create $ac_file" "$LINENO" 5 ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || as_fn_error "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit $? fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi # Messages printf '#================================================================\n' printf '# Ready to make.\n' printf '#================================================================\n' # END OF FILE qdbm-1.8.78/rlmgr.c0000644000175000017500000002503510610627747013052 0ustar mikiomikio/************************************************************************************************* * Utility for debugging Relic and its applications * Copyright (C) 2000-2007 Mikio Hirabayashi * This file is part of QDBM, Quick Database Manager. * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU * Lesser General Public License as published by the Free Software Foundation; either version * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * You should have received a copy of the GNU Lesser General Public License along with QDBM; if * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. *************************************************************************************************/ #include #include #include #include #include #include #include #include #undef TRUE #define TRUE 1 /* boolean true */ #undef FALSE #define FALSE 0 /* boolean false */ /* for RISC OS */ #if defined(__riscos__) || defined(__riscos) #include int __riscosify_control = __RISCOSIFY_NO_PROCESS; #endif /* global variables */ const char *progname; /* program name */ /* function prototypes */ int main(int argc, char **argv); void usage(void); char *hextoobj(const char *str, int *sp); int runcreate(int argc, char **argv); int runstore(int argc, char **argv); int rundelete(int argc, char **argv); int runfetch(int argc, char **argv); int runlist(int argc, char **argv); void pmyerror(const char *name, const char *msg); void printobj(const char *obj, int size); void printobjhex(const char *obj, int size); int docreate(char *name); int dostore(char *name, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int ins); int dodelete(char *name, const char *kbuf, int ksiz); int dofetch(char *name, const char *kbuf, int ksiz, int ox, int nb); int dolist(char *name, int ox); /* main routine */ int main(int argc, char **argv){ int rv; cbstdiobin(); progname = argv[0]; if(argc < 2) usage(); rv = 0; if(!strcmp(argv[1], "create")){ rv = runcreate(argc, argv); } else if(!strcmp(argv[1], "store")){ rv = runstore(argc, argv); } else if(!strcmp(argv[1], "delete")){ rv = rundelete(argc, argv); } else if(!strcmp(argv[1], "fetch")){ rv = runfetch(argc, argv); } else if(!strcmp(argv[1], "list")){ rv = runlist(argc, argv); } else { usage(); } return rv; } /* print the usage and exit */ void usage(void){ fprintf(stderr, "%s: administration utility for Relic\n", progname); fprintf(stderr, "\n"); fprintf(stderr, "usage:\n"); fprintf(stderr, " %s create name\n", progname); fprintf(stderr, " %s store [-kx] [-vx|-vf] [-insert] name key val\n", progname); fprintf(stderr, " %s delete [-kx] name key\n", progname); fprintf(stderr, " %s fetch [-kx] [-ox] [-n] name key\n", progname); fprintf(stderr, " %s list [-ox] name\n", progname); fprintf(stderr, "\n"); exit(1); } /* create a binary object from a hexadecimal string */ char *hextoobj(const char *str, int *sp){ char *buf, mbuf[3]; int len, i, j; len = strlen(str); if(!(buf = malloc(len + 1))) return NULL; j = 0; for(i = 0; i < len; i += 2){ while(strchr(" \n\r\t\f\v", str[i])){ i++; } if((mbuf[0] = str[i]) == '\0') break; if((mbuf[1] = str[i+1]) == '\0') break; mbuf[2] = '\0'; buf[j++] = (char)strtol(mbuf, NULL, 16); } buf[j] = '\0'; *sp = j; return buf; } /* parse arguments of create command */ int runcreate(int argc, char **argv){ char *name; int i, rv; name = NULL; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ usage(); } else if(!name){ name = argv[i]; } else { usage(); } } if(!name) usage(); rv = docreate(name); return rv; } /* parse arguments of store command */ int runstore(int argc, char **argv){ char *name, *key, *val, *kbuf, *vbuf; int i, kx, vx, vf, ins, ksiz, vsiz, rv; name = NULL; kx = FALSE; vx = FALSE; vf = FALSE; ins = FALSE; key = NULL; val = NULL; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ if(!strcmp(argv[i], "-kx")){ kx = TRUE; } else if(!strcmp(argv[i], "-vx")){ vx = TRUE; } else if(!strcmp(argv[i], "-vf")){ vf = TRUE; } else if(!strcmp(argv[i], "-insert")){ ins = TRUE; } else { usage(); } } else if(!name){ name = argv[i]; } else if(!key){ key = argv[i]; } else if(!val){ val = argv[i]; } else { usage(); } } if(!name || !key || !val) usage(); if(kx){ kbuf = hextoobj(key, &ksiz); } else { kbuf = cbmemdup(key, -1); ksiz = strlen(kbuf); } if(vx){ vbuf = hextoobj(val, &vsiz); } else if(vf){ vbuf = cbreadfile(val, &vsiz); } else { vbuf = cbmemdup(val, -1); vsiz = strlen(vbuf); } if(kbuf && vbuf){ rv = dostore(name, kbuf, ksiz, vbuf, vsiz, ins); } else { if(vf){ fprintf(stderr, "%s: %s: cannot read\n", progname, val); } else { fprintf(stderr, "%s: out of memory\n", progname); } rv = 1; } free(kbuf); free(vbuf); return rv; } /* parse arguments of delete command */ int rundelete(int argc, char **argv){ char *name, *key, *kbuf; int i, kx, ksiz, rv; name = NULL; kx = FALSE; key = NULL; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ if(!strcmp(argv[i], "-kx")){ kx = TRUE; } else { usage(); } } else if(!name){ name = argv[i]; } else if(!key){ key = argv[i]; } else { usage(); } } if(!name || !key) usage(); if(kx){ kbuf = hextoobj(key, &ksiz); } else { kbuf = cbmemdup(key, -1); ksiz = strlen(kbuf); } if(kbuf){ rv = dodelete(name, kbuf, ksiz); } else { fprintf(stderr, "%s: out of memory\n", progname); rv = 1; } free(kbuf); return rv; } /* parse arguments of fetch command */ int runfetch(int argc, char **argv){ char *name, *key, *kbuf; int i, kx, ox, nb, ksiz, rv; name = NULL; kx = FALSE; ox = FALSE; nb = FALSE; key = NULL; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ if(!strcmp(argv[i], "-kx")){ kx = TRUE; } else if(!strcmp(argv[i], "-ox")){ ox = TRUE; } else if(!strcmp(argv[i], "-n")){ nb = TRUE; } else { usage(); } } else if(!name){ name = argv[i]; } else if(!key){ key = argv[i]; } else { usage(); } } if(!name || !key) usage(); if(kx){ kbuf = hextoobj(key, &ksiz); } else { kbuf = cbmemdup(key, -1); ksiz = strlen(kbuf); } if(kbuf){ rv = dofetch(name, kbuf, ksiz, ox, nb); } else { fprintf(stderr, "%s: out of memory\n", progname); rv = 1; } free(kbuf); return rv; } /* parse arguments of list command */ int runlist(int argc, char **argv){ char *name; int i, ox, rv; name = NULL; ox = FALSE; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ if(!strcmp(argv[i], "-ox")){ ox = TRUE; } else { usage(); } } else if(!name){ name = argv[i]; } else { usage(); } } if(!name) usage(); rv = dolist(name, ox); return rv; } /* print an error message */ void pmyerror(const char *name, const char *msg){ fprintf(stderr, "%s: %s: %s\n", progname, name, msg); } /* print an object */ void printobj(const char *obj, int size){ int i; for(i = 0; i < size; i++){ putchar(obj[i]); } } /* print an object as a hexadecimal string */ void printobjhex(const char *obj, int size){ int i; for(i = 0; i < size; i++){ printf("%s%02X", i > 0 ? " " : "", ((const unsigned char *)obj)[i]); } } /* perform create command */ int docreate(char *name){ DBM *db; if(!(db = dbm_open(name, O_RDWR | O_CREAT | O_TRUNC, 00644))){ pmyerror(name, "dbm_open failed"); return 1; } dbm_close(db); return 0; } /* perform store command */ int dostore(char *name, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int ins){ DBM *db; datum key, content; int rv; if(!(db = dbm_open(name, O_RDWR, 00644))){ pmyerror(name, "dbm_open failed"); return 1; } key.dptr = (char *)kbuf; key.dsize = ksiz; content.dptr = (char *)vbuf; content.dsize = vsiz; switch(dbm_store(db, key, content, ins ? DBM_INSERT : DBM_REPLACE)){ case 0: rv = 0; break; case 1: pmyerror(name, "dbm_store failed by insert"); rv = 1; break; default: pmyerror(name, "dbm_store failed"); rv = 1; break; } dbm_close(db); return rv; } /* perform delete command */ int dodelete(char *name, const char *kbuf, int ksiz){ DBM *db; datum key; int rv; if(!(db = dbm_open((char *)name, O_RDWR, 00644))){ pmyerror(name, "dbm_open failed"); return 1; } key.dptr = (char *)kbuf; key.dsize = ksiz; if(dbm_delete(db, key) == 0){ rv = 0; } else { pmyerror(name, "dbm_delete failed"); rv = 1; } dbm_close(db); return rv; } /* perform fetch command */ int dofetch(char *name, const char *kbuf, int ksiz, int ox, int nb){ DBM *db; datum key, content; int rv; if(!(db = dbm_open((char *)name, O_RDONLY, 00644))){ pmyerror(name, "dbm_open failed"); return 1; } key.dptr = (char *)kbuf; key.dsize = ksiz; content = dbm_fetch(db, key); if(content.dptr){ if(ox){ printobjhex(content.dptr, content.dsize); } else { printobj(content.dptr, content.dsize); } if(!nb) putchar('\n'); rv = 0; } else { pmyerror(name, "dbm_fetch failed"); rv = 1; } dbm_close(db); return rv; } /* perform list command */ int dolist(char *name, int ox){ DBM *db; datum key, val; if(!(db = dbm_open((char *)name, O_RDONLY, 00644))){ pmyerror(name, "dbm_open failed"); return 1; } for(key = dbm_firstkey(db); key.dptr != NULL; key = dbm_nextkey(db)){ val = dbm_fetch(db, key); if(!val.dptr) break; if(ox){ printobjhex(key.dptr, key.dsize); putchar('\t'); printobjhex(val.dptr, val.dsize); } else { printobj(key.dptr, key.dsize); putchar('\t'); printobj(val.dptr, val.dsize); } putchar('\n'); } dbm_close(db); return 0; } /* END OF FILE */ qdbm-1.8.78/cabin.h0000644000175000017500000021241110573416530012776 0ustar mikiomikio/************************************************************************************************* * The utitlity API of QDBM * Copyright (C) 2000-2007 Mikio Hirabayashi * This file is part of QDBM, Quick Database Manager. * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU * Lesser General Public License as published by the Free Software Foundation; either version * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * You should have received a copy of the GNU Lesser General Public License along with QDBM; if * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. *************************************************************************************************/ #ifndef _CABIN_H /* duplication check */ #define _CABIN_H #if defined(__cplusplus) /* export for C++ */ extern "C" { #endif #include #include #if defined(_MSC_VER) && !defined(QDBM_INTERNAL) && !defined(QDBM_STATIC) #define MYEXTERN extern __declspec(dllimport) #else #define MYEXTERN extern #endif /************************************************************************************************* * API *************************************************************************************************/ #define CB_DATUMUNIT 12 /* allocation unit size of a datum handle */ #define CB_LISTUNIT 64 /* allocation unit number of a list handle */ #define CB_MAPBNUM 4093 /* bucket size of a map handle */ typedef struct { /* type of structure for a basic datum */ char *dptr; /* pointer to the region */ int dsize; /* size of the region */ int asize; /* size of the allocated region */ } CBDATUM; typedef struct { /* type of structure for an element of a list */ char *dptr; /* pointer to the region */ int dsize; /* size of the effective region */ } CBLISTDATUM; typedef struct { /* type of structure for a list */ CBLISTDATUM *array; /* array of data */ int anum; /* number of the elements of the array */ int start; /* start index of using elements */ int num; /* number of using elements */ } CBLIST; typedef struct _CBMAPDATUM { /* type of structure for an element of a map */ int ksiz; /* size of the region of the key */ int vsiz; /* size of the region of the value */ int hash; /* second hash value */ struct _CBMAPDATUM *left; /* pointer to the left child */ struct _CBMAPDATUM *right; /* pointer to the right child */ struct _CBMAPDATUM *prev; /* pointer to the previous element */ struct _CBMAPDATUM *next; /* pointer to the next element */ } CBMAPDATUM; typedef struct { /* type of structure for a map */ CBMAPDATUM **buckets; /* bucket array */ CBMAPDATUM *first; /* pointer to the first element */ CBMAPDATUM *last; /* pointer to the last element */ CBMAPDATUM *cur; /* pointer to the current element */ int bnum; /* number of buckets */ int rnum; /* number of records */ } CBMAP; typedef struct { /* type of structure for a heap */ char *base; /* base pointer */ char *swap; /* region for swapping */ int size; /* size of each record */ int num; /* currnet number of records */ int max; /* maximum number of records */ int(*compar)(const void *, const void *); /* comparing function */ } CBHEAP; /* Call back function for handling a fatal error. The argument specifies the error message. The initial value of this variable is `NULL'. If the value is `NULL', the default function is called when a fatal error occurs. A fatal error occurs when memory allocation is failed. */ MYEXTERN void (*cbfatalfunc)(const char *); /* Allocate a region on memory. `size' specifies the size of the region. The return value is the pointer to the allocated region. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. */ void *cbmalloc(size_t size); /* Re-allocate a region on memory. `ptr' specifies the pointer to a region. `size' specifies the size of the region. The return value is the pointer to the re-allocated region. Because the region of the return value is allocated with the `realloc' call, it should be released with the `free' call if it is no longer in use. */ void *cbrealloc(void *ptr, size_t size); /* Duplicate a region on memory. `ptr' specifies the pointer to a region. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. The return value is the pointer to the allocated region of the duplicate. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. */ char *cbmemdup(const char *ptr, int size); /* Free a region on memory. `ptr' specifies the pointer to a region. If it is `NULL', this function has no effect. Although this function is just a wrapper of `free' call, this is useful in applications using another package of the `malloc' series. */ void cbfree(void *ptr); /* Register the pointer or handle of an object to the global garbage collector. `ptr' specifies the pointer or handle of an object. `func' specifies the pointer to a function to release resources of the object. Its argument is the pointer or handle of the object to release. This function assures that resources of an object are released when the process exits normally by returning from the `main' function or calling the `exit' function. */ void cbglobalgc(void *ptr, void (*func)(void *)); /* Exercise the global garbage collector explicitly. Note that you should not use objects registered to the global garbage collector any longer after calling this function. Because the global garbage collecter is initialized and you can register new objects into it. */ void cbggcsweep(void); /* Check availability of allocation of the virtual memory. `size' specifies the size of region to be allocated newly. The return value is true if allocation should be success, or false if not. */ int cbvmemavail(size_t size); /* Sort an array using insert sort. `base' spacifies the pointer to an array. `nmemb' specifies the number of elements of the array. `size' specifies the size of each element. `compar' specifies the pointer to comparing function. The two arguments specify the pointers of elements. The comparing function should returns positive if the former is big, negative if the latter is big, 0 if both are equal. Insert sort is useful only if most elements have been sorted already. */ void cbisort(void *base, int nmemb, int size, int(*compar)(const void *, const void *)); /* Sort an array using shell sort. `base' spacifies the pointer to an array. `nmemb' specifies the number of elements of the array. `size' specifies the size of each element. `compar' specifies the pointer to comparing function. The two arguments specify the pointers of elements. The comparing function should returns positive if the former is big, negative if the latter is big, 0 if both are equal. If most elements have been sorted, shell sort may be faster than heap sort or quick sort. */ void cbssort(void *base, int nmemb, int size, int(*compar)(const void *, const void *)); /* Sort an array using heap sort. `base' spacifies the pointer to an array. `nmemb' specifies the number of elements of the array. `size' specifies the size of each element. `compar' specifies the pointer to comparing function. The two arguments specify the pointers of elements. The comparing function should returns positive if the former is big, negative if the latter is big, 0 if both are equal. Although heap sort is robust against bias of input, quick sort is faster in most cases. */ void cbhsort(void *base, int nmemb, int size, int(*compar)(const void *, const void *)); /* Sort an array using quick sort. `base' spacifies the pointer to an array. `nmemb' specifies the number of elements of the array. `size' specifies the size of each element. `compar' specifies the pointer to comparing function. The two arguments specify the pointers of elements. The comparing function should returns positive if the former is big, negative if the latter is big, 0 if both are equal. Being sensitive to bias of input, quick sort is the fastest sorting algorithm. */ void cbqsort(void *base, int nmemb, int size, int(*compar)(const void *, const void *)); /* Compare two strings with case insensitive evaluation. `astr' specifies the pointer of one string. `astr' specifies the pointer of the other string. The return value is positive if the former is big, negative if the latter is big, 0 if both are equivalent. Upper cases and lower cases of alphabets in ASCII code are not distinguished. */ int cbstricmp(const char *astr, const char *bstr); /* Check whether a string begins with a key. `str' specifies the pointer of a target string. `key' specifies the pointer of a forward matching key string. The return value is true if the target string begins with the key, else, it is false. */ int cbstrfwmatch(const char *str, const char *key); /* Check whether a string begins with a key, with case insensitive evaluation. `str' specifies the pointer of a target string. `key' specifies the pointer of a forward matching key string. The return value is true if the target string begins with the key, else, it is false. Upper cases and lower cases of alphabets in ASCII code are not distinguished. */ int cbstrfwimatch(const char *str, const char *key); /* Check whether a string ends with a key. `str' specifies the pointer of a target string. `key' specifies the pointer of a backward matching key string. The return value is true if the target string ends with the key, else, it is false. */ int cbstrbwmatch(const char *str, const char *key); /* Check whether a string ends with a key, with case insensitive evaluation. `str' specifies the pointer of a target string. `key' specifies the pointer of a backward matching key string. The return value is true if the target string ends with the key, else, it is false. Upper cases and lower cases of alphabets in ASCII code are not distinguished. */ int cbstrbwimatch(const char *str, const char *key); /* Locate a substring in a string using KMP method. `haystack' specifies the pointer of a target string. `needle' specifies the pointer of a substring to be found. The return value is the pointer to the beginning of the substring or `NULL' if the substring is not found. In most cases, `strstr' as a built-in function of the compiler is faster than this function. */ char *cbstrstrkmp(const char *haystack, const char *needle); /* Locate a substring in a string using BM method. `haystack' specifies the pointer of a target string. `needle' specifies the pointer of a substring to be found. The return value is the pointer to the beginning of the substring or `NULL' if the substring is not found. In most cases, `strstr' as a built-in function of the compiler is faster than this function. */ char *cbstrstrbm(const char *haystack, const char *needle); /* Convert the letters of a string to upper case. `str' specifies the pointer of a string to convert. The return value is the pointer to the string. */ char *cbstrtoupper(char *str); /* Convert the letters of a string to lower case. `str' specifies the pointer of a string to convert. The return value is the pointer to the string. */ char *cbstrtolower(char *str); /* Cut space characters at head or tail of a string. `str' specifies the pointer of a string to convert. The return value is the pointer to the string. */ char *cbstrtrim(char *str); /* Squeeze space characters in a string and trim it. `str' specifies the pointer of a string to convert. The return value is the pointer to the string. */ char *cbstrsqzspc(char *str); /* Count the number of characters in a string of UTF-8. `str' specifies the pointer of a string of UTF-8. The return value is the number of characters in the string. */ int cbstrcountutf(const char *str); /* Cut a string of UTF-8 at the specified number of characters. `str' specifies the pointer of a string of UTF-8. `num' specifies the number of characters to be kept. The return value is the pointer to the string. */ char *cbstrcututf(char *str, int num); /* Get a datum handle. `ptr' specifies the pointer to the region of the initial content. If it is `NULL', an empty datum is created. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. The return value is a datum handle. */ CBDATUM *cbdatumopen(const char *ptr, int size); /* Copy a datum. `datum' specifies a datum handle. The return value is a new datum handle. */ CBDATUM *cbdatumdup(const CBDATUM *datum); /* Free a datum handle. `datum' specifies a datum handle. Because the region of a closed handle is released, it becomes impossible to use the handle. */ void cbdatumclose(CBDATUM *datum); /* Concatenate a datum and a region. `datum' specifies a datum handle. `ptr' specifies the pointer to the region to be appended. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. */ void cbdatumcat(CBDATUM *datum, const char *ptr, int size); /* Get the pointer of the region of a datum. `datum' specifies a datum handle. The return value is the pointer of the region of a datum. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. */ const char *cbdatumptr(const CBDATUM *datum); /* Get the size of the region of a datum. `datum' specifies a datum handle. The return value is the size of the region of a datum. */ int cbdatumsize(const CBDATUM *datum); /* Change the size of the region of a datum. `datum' specifies a datum handle. `size' specifies the new size of the region. If the new size is bigger than the one of old, the surplus region is filled with zero codes. */ void cbdatumsetsize(CBDATUM *datum, int size); /* Perform formatted output into a datum. `format' specifies a printf-like format string. The conversion character `%' can be used with such flag characters as `s', `d', `o', `u', `x', `X', `c', `e', `E', `f', `g', `G', `@', `?', `:', `%'. `@' works as with `s' but escapes meta characters of XML. `?' works as with `s' but escapes meta characters of URL. `:' works as with `s' but performs MIME encoding as UTF-8. The other conversion character work as with each original. */ void cbdatumprintf(CBDATUM *datum, const char *format, ...); /* Convert a datum to an allocated region. `datum' specifies a datum handle. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. The return value is the pointer to the region of the datum. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. Because the region of the original datam is released, it should not be released again. */ char *cbdatumtomalloc(CBDATUM *datum, int *sp); /* Get a list handle. The return value is a list handle. */ CBLIST *cblistopen(void); /* Copy a list. `list' specifies a list handle. The return value is a new list handle. */ CBLIST *cblistdup(const CBLIST *list); /* Close a list handle. `list' specifies a list handle. Because the region of a closed handle is released, it becomes impossible to use the handle. */ void cblistclose(CBLIST *list); /* Get the number of elements of a list. `list' specifies a list handle. The return value is the number of elements of the list. */ int cblistnum(const CBLIST *list); /* Get the pointer to the region of an element of a list. `list' specifies a list handle. `index' specifies the index of an element. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. The return value is the pointer to the region of the value. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. If `index' is equal to or more than the number of elements, the return value is `NULL'. */ const char *cblistval(const CBLIST *list, int index, int *sp); /* Add an element at the end of a list. `list' specifies a list handle. `ptr' specifies the pointer to the region of an element. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. */ void cblistpush(CBLIST *list, const char *ptr, int size); /* Remove an element of the end of a list. `list' specifies a list handle. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. The return value is the pointer to the region of the value. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. If the list is empty, the return value is `NULL'. */ char *cblistpop(CBLIST *list, int *sp); /* Add an element at the top of a list. `list' specifies a list handle. `ptr' specifies the pointer to the region of an element. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. */ void cblistunshift(CBLIST *list, const char *ptr, int size); /* Remove an element of the top of a list. `list' specifies a list handle. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. The return value is the pointer to the region of the value. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. If the list is empty, the return value is `NULL'. */ char *cblistshift(CBLIST *list, int *sp); /* Add an element at the specified location of a list. `list' specifies a list handle. `index' specifies the index of an element. `ptr' specifies the pointer to the region of the element. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. */ void cblistinsert(CBLIST *list, int index, const char *ptr, int size); /* Remove an element at the specified location of a list. `list' specifies a list handle. `index' specifies the index of an element. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. The return value is the pointer to the region of the value. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. If `index' is equal to or more than the number of elements, no element is removed and the return value is `NULL'. */ char *cblistremove(CBLIST *list, int index, int *sp); /* Overwrite an element at the specified location of a list. `list' specifies a list handle. `index' specifies the index of an element. `ptr' specifies the pointer to the region of the new content. `size' specifies the size of the new content. If it is negative, the size is assigned with `strlen(ptr)'. If `index' is equal to or more than the number of elements, this function has no effect. */ void cblistover(CBLIST *list, int index, const char *ptr, int size); /* Sort elements of a list in lexical order. `list' specifies a list handle. Quick sort is used for sorting. */ void cblistsort(CBLIST *list); /* Search a list for an element using liner search. `list' specifies a list handle. `ptr' specifies the pointer to the region of a key. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. The return value is the index of a corresponding element or -1 if there is no corresponding element. If two or more elements corresponds, the former returns. */ int cblistlsearch(const CBLIST *list, const char *ptr, int size); /* Search a list for an element using binary search. `list' specifies a list handle. It should be sorted in lexical order. `ptr' specifies the pointer to the region of a key. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. The return value is the index of a corresponding element or -1 if there is no corresponding element. If two or more elements corresponds, which returns is not defined. */ int cblistbsearch(const CBLIST *list, const char *ptr, int size); /* Serialize a list into a byte array. `list' specifies a list handle. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. The return value is the pointer to the region of the result serial region. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. */ char *cblistdump(const CBLIST *list, int *sp); /* Redintegrate a serialized list. `ptr' specifies the pointer to a byte array. `size' specifies the size of the region. The return value is a new list handle. */ CBLIST *cblistload(const char *ptr, int size); /* Get a map handle. The return value is a map handle. */ CBMAP *cbmapopen(void); /* Copy a map. `map' specifies a map handle. The return value is a new map handle. The iterator of the source map is initialized. */ CBMAP *cbmapdup(CBMAP *map); /* Close a map handle. `map' specifies a map handle. Because the region of a closed handle is released, it becomes impossible to use the handle. */ void cbmapclose(CBMAP *map); /* Store a record into a map. `map' specifies a map handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `vbuf' specifies the pointer to the region of a value. `vsiz' specifies the size of the region of the value. If it is negative, the size is assigned with `strlen(vbuf)'. `over' specifies whether the value of the duplicated record is overwritten or not. If `over' is false and the key is duplicated, the return value is false, else, it is true. */ int cbmapput(CBMAP *map, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int over); /* Concatenate a value at the end of the value of the existing record. `map' specifies a map handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `vbuf' specifies the pointer to the region of a value. `vsiz' specifies the size of the region of the value. If it is negative, the size is assigned with `strlen(vbuf)'. If there is no corresponding record, a new record is created. */ void cbmapputcat(CBMAP *map, const char *kbuf, int ksiz, const char *vbuf, int vsiz); /* Delete a record in a map. `map' specifies a map handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. If successful, the return value is true. False is returned when no record corresponds to the specified key. */ int cbmapout(CBMAP *map, const char *kbuf, int ksiz); /* Retrieve a record in a map. `map' specifies a map handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the region of the value of the corresponding record. `NULL' is returned when no record corresponds. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. */ const char *cbmapget(const CBMAP *map, const char *kbuf, int ksiz, int *sp); /* Move a record to the edge of a map. `map' specifies a map handle. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `head' specifies the destination which is head if it is true or tail if else. If successful, the return value is true. False is returned when no record corresponds to the specified key. */ int cbmapmove(CBMAP *map, const char *kbuf, int ksiz, int head); /* Initialize the iterator of a map. `map' specifies a map handle. The iterator is used in order to access the key of every record stored in a map. */ void cbmapiterinit(CBMAP *map); /* Get the next key of the iterator of a map. `map' specifies a map handle. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the region of the next key, else, it is `NULL'. `NULL' is returned when no record is to be get out of the iterator. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. The order of iteration is assured to be the same of the one of storing. */ const char *cbmapiternext(CBMAP *map, int *sp); /* Get the value binded to the key fetched from the iterator of a map. `kbuf' specifies the pointer to the region of a iteration key. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. The return value is the pointer to the region of the value of the corresponding record. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. */ const char *cbmapiterval(const char *kbuf, int *sp); /* Get the number of the records stored in a map. `map' specifies a map handle. The return value is the number of the records stored in the map. */ int cbmaprnum(const CBMAP *map); /* Get the list handle contains all keys in a map. `map' specifies a map handle. The return value is the list handle contains all keys in the map. Because the handle of the return value is opened with the function `cblistopen', it should be closed with the function `cblistclose' if it is no longer in use. */ CBLIST *cbmapkeys(CBMAP *map); /* Get the list handle contains all values in a map. `map' specifies a map handle. The return value is the list handle contains all values in the map. Because the handle of the return value is opened with the function `cblistopen', it should be closed with the function `cblistclose' if it is no longer in use. */ CBLIST *cbmapvals(CBMAP *map); /* Serialize a map into a byte array. `map' specifies a map handle. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. The return value is the pointer to the region of the result serial region. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. */ char *cbmapdump(CBMAP *map, int *sp); /* Redintegrate a serialized map. `ptr' specifies the pointer to a byte array. `size' specifies the size of the region. The return value is a new map handle. */ CBMAP *cbmapload(const char *ptr, int size); /* Extract a record from a serialized map. `ptr' specifies the pointer to a byte array. `size' specifies the size of the region. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the region of the key. If it is negative, the size is assigned with `strlen(kbuf)'. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the region of the value of the corresponding record. `NULL' is returned when no record corresponds. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. */ char *cbmaploadone(const char *ptr, int size, const char *kbuf, int ksiz, int *sp); /* Get a heap handle. `size' specifies the size of each record. `max' specifies the maximum number of records in the heap. `compar' specifies the pointer to comparing function. The two arguments specify the pointers of records. The comparing function should returns positive if the former is big, negative if the latter is big, 0 if both are equal. The return value is a heap handle. */ CBHEAP *cbheapopen(int size, int max, int(*compar)(const void *, const void *)); /* Copy a heap. `heap' specifies a heap handle. The return value is a new heap handle. */ CBHEAP *cbheapdup(CBHEAP *heap); /* Close a heap handle. `heap' specifies a heap handle. Because the region of a closed handle is released, it becomes impossible to use the handle. */ void cbheapclose(CBHEAP *heap); /* Get the number of the records stored in a heap. `heap' specifies a heap handle. The return value is the number of the records stored in the heap. */ int cbheapnum(CBHEAP *heap); /* Insert a record into a heap. `heap' specifies a heap handle. `ptr' specifies the pointer to the region of a record. The return value is true if the record is added, else false. If the new record is bigger than the biggest existing regord, the new record is not added. If the new record is added and the number of records exceeds the maximum number, the biggest existing record is removed. */ int cbheapinsert(CBHEAP *heap, const void *ptr); /* Get the pointer to the region of a record in a heap. `heap' specifies a heap handle. `index' specifies the index of a record. The return value is the pointer to the region of the record. If `index' is equal to or more than the number of records, the return value is `NULL'. Note that records are organized by the nagative order the comparing function. */ const void *cbheapval(CBHEAP *heap, int index); /* Convert a heap to an allocated region. `heap' specifies a heap handle. `np' specifies the pointer to a variable to which the number of records of the return value is assigned. If it is `NULL', it is not used. The return value is the pointer to the region of the heap. Records are sorted. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. Because the region of the original heap is released, it should not be released again. */ void *cbheaptomalloc(CBHEAP *heap, int *np); /* Allocate a formatted string on memory. `format' specifies a printf-like format string. The conversion character `%' can be used with such flag characters as `d', `o', `u', `x', `X', `e', `E', `f', `g', `G', `c', `s', and `%'. Specifiers of the field length and the precision can be put between the conversion characters and the flag characters. The specifiers consist of decimal characters, `.', `+', `-', and the space character. The other arguments are used according to the format string. The return value is the pointer to the allocated region of the result string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. */ char *cbsprintf(const char *format, ...); /* Replace some patterns in a string. `str' specifies the pointer to a source string. `pairs' specifies the handle of a map composed of pairs of replacement. The key of each pair specifies a pattern before replacement and its value specifies the pattern after replacement. The return value is the pointer to the allocated region of the result string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. */ char *cbreplace(const char *str, CBMAP *pairs); /* Make a list by splitting a serial datum. `ptr' specifies the pointer to the region of the source content. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. `delim' specifies a string containing delimiting characters. If it is `NULL', zero code is used as a delimiter. The return value is a list handle. If two delimiters are successive, it is assumed that an empty element is between the two. Because the handle of the return value is opened with the function `cblistopen', it should be closed with the function `cblistclose'. */ CBLIST *cbsplit(const char *ptr, int size, const char *delim); /* Read whole data of a file. `name' specifies the name of a file. If it is `NULL', the standard input is specified. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. The return value is the pointer to the allocated region of the read data. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. */ char *cbreadfile(const char *name, int *sp); /* Write a serial datum into a file. `name specifies the name of a file. If it is `NULL', the standard output is specified. `ptr' specifies the pointer to the region of the source content. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. If successful, the return value is true, else, it is false. If the file exists, it is overwritten. Else, a new file is created. */ int cbwritefile(const char *name, const char *ptr, int size); /* Read every line of a file. `name' specifies the name of a file. If it is `NULL', the standard input is specified. The return value is a list handle of the lines if successful, else it is NULL. Line separators are cut out. Because the handle of the return value is opened with the function `cblistopen', it should be closed with the function `cblistclose' if it is no longer in use. */ CBLIST *cbreadlines(const char *name); /* Read names of files in a directory. `name' specifies the name of a directory. The return value is a list handle of names if successful, else it is NULL. Because the handle of the return value is opened with the function `cblistopen', it should be closed with the function `cblistclose' if it is no longer in use. */ CBLIST *cbdirlist(const char *name); /* Get the status of a file or a directory. `name' specifies the name of a file or a directory. `dirp' specifies the pointer to a variable to which whether the file is a directory is assigned. If it is `NULL', it is not used. `sizep' specifies the pointer to a variable to which the size of the file is assigned. If it is `NULL', it is not used. `mtimep' specifies the pointer to a variable to which the last modified time of the file is assigned. If it is `NULL', it is not used. If successful, the return value is true, else, false. False is returned when the file does not exist or the permission is denied. */ int cbfilestat(const char *name, int *isdirp, int *sizep, time_t *mtimep); /* Remove a file or a directory and its sub ones recursively. `name' specifies the name of a file or a directory. If successful, the return value is true, else, false. False is returned when the file does not exist or the permission is denied. */ int cbremove(const char *name); /* Break up a URL into elements. `str' specifies the pointer to a string of URL. The return value is a map handle. Each key of the map is the name of an element. The key "self" specifies the URL itself. The key "scheme" specifies the scheme. The key "host" specifies the host of the server. The key "port" specifies the port number of the server. The key "authority" specifies the authority information. The key "path" specifies the path of the resource. The key "file" specifies the file name without the directory section. The key "query" specifies the query string. The key "fragment" specifies the fragment string. Supported schema are HTTP, HTTPS, FTP, and FILE. Absolute URL and relative URL are supported. Because the handle of the return value is opened with the function `cbmapopen', it should be closed with the function `cbmapclose' if it is no longer in use. */ CBMAP *cburlbreak(const char *str); /* Resolve a relative URL with another absolute URL. `base' specifies an absolute URL of a base location. `target' specifies a URL to be resolved. The return value is a resolved URL. If the target URL is relative, a new URL of relative location from the base location is returned. Else, a copy of the target URL is returned. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. */ char *cburlresolve(const char *base, const char *target); /* Encode a serial object with URL encoding. `ptr' specifies the pointer to a region. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. The return value is the pointer to the result string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. */ char *cburlencode(const char *ptr, int size); /* Decode a string encoded with URL encoding. `str' specifies the pointer to an encoded string. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. The return value is the pointer to the region of the result. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. */ char *cburldecode(const char *str, int *sp); /* Encode a serial object with Base64 encoding. `ptr' specifies the pointer to a region. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. The return value is the pointer to the result string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. */ char *cbbaseencode(const char *ptr, int size); /* Decode a string encoded with Base64 encoding. `str' specifies the pointer to an encoded string. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. The return value is the pointer to the region of the result. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. */ char *cbbasedecode(const char *str, int *sp); /* Encode a serial object with quoted-printable encoding. `ptr' specifies the pointer to a region. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. The return value is the pointer to the result string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. */ char *cbquoteencode(const char *ptr, int size); /* Decode a string encoded with quoted-printable encoding. `str' specifies the pointer to an encoded string. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. The return value is the pointer to the region of the result. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. */ char *cbquotedecode(const char *str, int *sp); /* Split a string of MIME into headers and the body. `ptr' specifies the pointer to the region of MIME data. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. `attrs' specifies a map handle to store attributes. If it is `NULL', it is not used. Each key of the map is an attribute name uncapitalized. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. The return value is the pointer of the body data. If the content type is defined, the attribute map has the key "TYPE" specifying the type. If the character encoding is defined, the key "CHARSET" specifies the encoding name. If the boundary string of multipart is defined, the key "BOUNDARY" specifies the string. If the content disposition is defined, the key "DISPOSITION" specifies the direction. If the file name is defined, the key "FILENAME" specifies the name. If the attribute name is defined, the key "NAME" specifies the name. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. */ char *cbmimebreak(const char *ptr, int size, CBMAP *attrs, int *sp); /* Split multipart data of MIME into its parts. `ptr' specifies the pointer to the region of multipart data of MIME. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. `boundary' specifies the pointer to the region of the boundary string. The return value is a list handle. Each element of the list is the string of a part. Because the handle of the return value is opened with the function `cblistopen', it should be closed with the function `cblistclose' if it is no longer in use. */ CBLIST *cbmimeparts(const char *ptr, int size, const char *boundary); /* Encode a string with MIME encoding. `str' specifies the pointer to a string. `encname' specifies a string of the name of the character encoding. The return value is the pointer to the result string. `base' specifies whether to use Base64 encoding. If it is false, quoted-printable is used. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. */ char *cbmimeencode(const char *str, const char *encname, int base); /* Decode a string encoded with MIME encoding. `str' specifies the pointer to an encoded string. `enp' specifies the pointer to a region into which the name of encoding is written. If it is `NULL', it is not used. The size of the buffer should be equal to or more than 32 bytes. The return value is the pointer to the result string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. */ char *cbmimedecode(const char *str, char *enp); /* Split a string of CSV into rows. `str' specifies the pointer to the region of an CSV string. The return value is a list handle. Each element of the list is a string of a row. Because the handle of the return value is opened with the function `cblistopen', it should be closed with the function `cblistclose' if it is no longer in use. The character encoding of the input string should be US-ASCII, UTF-8, ISO-8859-*, EUC-*, or Shift_JIS. Being compatible with MS-Excel, these functions for CSV can handle cells including such meta characters as comma, between double quotation marks. */ CBLIST *cbcsvrows(const char *str); /* Split the string of a row of CSV into cells. `str' specifies the pointer to the region of a row of CSV. The return value is a list handle. Each element of the list is the unescaped string of a cell of the row. Because the handle of the return value is opened with the function `cblistopen', it should be closed with the function `cblistclose' if it is no longer in use. */ CBLIST *cbcsvcells(const char *str); /* Escape a string with the meta characters of CSV. `str' specifies the pointer to the region of a string. The return value is the pointer to the escaped string sanitized of meta characters. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. */ char *cbcsvescape(const char *str); /* Unescape a string with the escaped meta characters of CSV. `str' specifies the pointer to the region of a string with meta characters. The return value is the pointer to the unescaped string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. */ char *cbcsvunescape(const char *str); /* Split a string of XML into tags and text sections. `str' specifies the pointer to the region of an XML string. `cr' specifies whether to remove comments. The return value is a list handle. Each element of the list is the string of a tag or a text section. Because the handle of the return value is opened with the function `cblistopen', it should be closed with the function `cblistclose' if it is no longer in use. The character encoding of the input string should be US-ASCII, UTF-8, ISO-8859-*, EUC-*, or Shift_JIS. Because these functions for XML are not XML parser with validation check, it can handle also HTML and SGML. */ CBLIST *cbxmlbreak(const char *str, int cr); /* Get the map of attributes of an XML tag. `str' specifies the pointer to the region of a tag string. The return value is a map handle. Each key of the map is the name of an attribute. Each value is unescaped. You can get the name of the tag with the key of an empty string. Because the handle of the return value is opened with the function `cbmapopen', it should be closed with the function `cbmapclose' if it is no longer in use. */ CBMAP *cbxmlattrs(const char *str); /* Escape a string with the meta characters of XML. `str' specifies the pointer to the region of a string. The return value is the pointer to the escaped string sanitized of meta characters. This function converts only `&', `<', `>', and `"'. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. */ char *cbxmlescape(const char *str); /* Unescape a string with the entity references of XML. `str' specifies the pointer to the region of a string with meta characters. The return value is the pointer to the unescaped string. This function restores only `&', `<', `>', and `"'. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. */ char *cbxmlunescape(const char *str); /* Compress a serial object with ZLIB. `ptr' specifies the pointer to a region. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If successful, the return value is the pointer to the result object, else, it is `NULL'. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. This function is available only if QDBM was built with ZLIB enabled. */ char *cbdeflate(const char *ptr, int size, int *sp); /* Decompress a serial object compressed with ZLIB. `ptr' specifies the pointer to a region. `size' specifies the size of the region. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the result object, else, it is `NULL'. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. This function is available only if QDBM was built with ZLIB enabled. */ char *cbinflate(const char *ptr, int size, int *sp); /* Compress a serial object with GZIP. `ptr' specifies the pointer to a region. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If successful, the return value is the pointer to the result object, else, it is `NULL'. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. This function is available only if QDBM was built with ZLIB enabled. */ char *cbgzencode(const char *ptr, int size, int *sp); /* Decompress a serial object compressed with GZIP. `ptr' specifies the pointer to a region. `size' specifies the size of the region. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the result object, else, it is `NULL'. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. This function is available only if QDBM was built with ZLIB enabled. */ char *cbgzdecode(const char *ptr, int size, int *sp); /* Get the CRC32 checksum of a serial object. `ptr' specifies the pointer to a region. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. The return value is the CRC32 checksum of the object. This function is available only if QDBM was built with ZLIB enabled. */ unsigned int cbgetcrc(const char *ptr, int size); /* Compress a serial object with LZO. `ptr' specifies the pointer to a region. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If successful, the return value is the pointer to the result object, else, it is `NULL'. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. This function is available only if QDBM was built with LZO enabled. */ char *cblzoencode(const char *ptr, int size, int *sp); /* Decompress a serial object compressed with LZO. `ptr' specifies the pointer to a region. `size' specifies the size of the region. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the result object, else, it is `NULL'. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. This function is available only if QDBM was built with LZO enabled. */ char *cblzodecode(const char *ptr, int size, int *sp); /* Compress a serial object with BZIP2. `ptr' specifies the pointer to a region. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If successful, the return value is the pointer to the result object, else, it is `NULL'. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. This function is available only if QDBM was built with LZO enabled. */ char *cbbzencode(const char *ptr, int size, int *sp); /* Decompress a serial object compressed with BZIP2. `ptr' specifies the pointer to a region. `size' specifies the size of the region. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the result object, else, it is `NULL'. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. This function is available only if QDBM was built with LZO enabled. */ char *cbbzdecode(const char *ptr, int size, int *sp); /* Convert the character encoding of a string. `ptr' specifies the pointer to a region. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. `icode' specifies the name of encoding of the input string. `ocode' specifies the name of encoding of the output string. `sp' specifies the pointer to a variable to which the size of the region of the return value is assigned. If it is `NULL', it is not used. `mp' specifies the pointer to a variable to which the number of missing characters by failure of conversion is assigned. If it is `NULL', it is not used. If successful, the return value is the pointer to the result object, else, it is `NULL'. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. This function is available only if QDBM was built with ICONV enabled. */ char *cbiconv(const char *ptr, int size, const char *icode, const char *ocode, int *sp, int *mp); /* Detect the encoding of a string automatically. `ptr' specifies the pointer to a region. `size' specifies the size of the region. If it is negative, the size is assigned with `strlen(ptr)'. The return value is the string of the encoding name of the string. As it stands, US-ASCII, ISO-2022-JP, Shift_JIS, CP932, EUC-JP, UTF-8, UTF-16, UTF-16BE, and UTF-16LE are supported. If none of them matches, ISO-8859-1 is selected. This function is available only if QDBM was built with ICONV enabled. */ const char *cbencname(const char *ptr, int size); /* Get the jet lag of the local time in seconds. The return value is the jet lag of the local time in seconds. */ int cbjetlag(void); /* Get the Gregorian calendar of a time. `t' specifies a source time. If it is negative, the current time is specified. `jl' specifies the jet lag of a location in seconds. `yearp' specifies the pointer to a variable to which the year is assigned. If it is `NULL', it is not used. `monp' specifies the pointer to a variable to which the month is assigned. If it is `NULL', it is not used. 1 means January and 12 means December. `dayp' specifies the pointer to a variable to which the day of the month is assigned. If it is `NULL', it is not used. `hourp' specifies the pointer to a variable to which the hours is assigned. If it is `NULL', it is not used. `minp' specifies the pointer to a variable to which the minutes is assigned. If it is `NULL', it is not used. `secp' specifies the pointer to a variable to which the seconds is assigned. If it is `NULL', it is not used. */ void cbcalendar(time_t t, int jl, int *yearp, int *monp, int *dayp, int *hourp, int *minp, int *secp); /* Get the day of week of a date. `year' specifies the year of a date. `mon' specifies the month of the date. `day' specifies the day of the date. The return value is the day of week of the date. 0 means Sunday and 6 means Saturday. */ int cbdayofweek(int year, int mon, int day); /* Get the string for a date in W3CDTF. `t' specifies a source time. If it is negative, the current time is specified. `jl' specifies the jet lag of a location in seconds. The return value is the string of the date in W3CDTF (YYYY-MM-DDThh:mm:ddTZD). Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. */ char *cbdatestrwww(time_t t, int jl); /* Get the string for a date in RFC 1123 format. `t' specifies a source time. If it is negative, the current time is specified. `jl' specifies the jet lag of a location in seconds. The return value is the string of the date in RFC 1123 format (Wdy, DD-Mon-YYYY hh:mm:dd TZD). Because the region of the return value is allocated with the `malloc' call, it should be released with the `free' call if it is no longer in use. */ char *cbdatestrhttp(time_t t, int jl); /* Get the time value of a date string in decimal, hexadecimal, W3CDTF, or RFC 822 (1123). `str' specifies a date string in decimal, hexadecimal, W3CDTF, or RFC 822 (1123). The return value is the time value of the date or -1 if the format is invalid. Decimal can be trailed by "s" for in seconds, "m" for in minutes, "h" for in hours, and "d" for in days. */ time_t cbstrmktime(const char *str); /* Get user and system processing times. `usrp' specifies the pointer to a variable to which the user processing time is assigned. If it is `NULL', it is not used. The unit of time is seconds. `sysp' specifies the pointer to a variable to which the system processing time is assigned. If it is `NULL', it is not used. The unit of time is seconds. */ void cbproctime(double *usrp, double *sysp); /* Ensure that the standard I/O is binary mode. This function is useful for applications on dosish file systems. */ void cbstdiobin(void); /************************************************************************************************* * features for experts *************************************************************************************************/ /* Show error message on the standard error output and exit. `message' specifies an error message. This function does not return. */ void *cbmyfatal(const char *message); /* Create a datum handle from an allocated region. `ptr' specifies the pointer to the region of an element. The region should be allocated with malloc and it is released by the function. `size' specifies the size of the region. */ CBDATUM *cbdatumopenbuf(char *ptr, int size); /* Set a buffer to a datum handle. `ptr' specifies the pointer to the region of an element. The region should be allocated with malloc and it is released by the function. `size' specifies the size of the region. */ void cbdatumsetbuf(CBDATUM *datum, char *ptr, int size); /* Add an allocated element at the end of a list. `list' specifies a list handle. `ptr' specifies the pointer to the region of an element. The region should be allocated with malloc and it is released by the function. `size' specifies the size of the region. */ void cblistpushbuf(CBLIST *list, char *ptr, int size); /* Get a map handle with specifying the number of buckets. `bnum' specifies the number of buckets. The return value is a map handle. */ CBMAP *cbmapopenex(int bnum); /* Alias of `cbmalloc'. */ #define CB_MALLOC(CB_ptr, CB_size) \ (((CB_ptr) = malloc(CB_size)) ? (CB_ptr) : cbmyfatal("out of memory")) /* Alias of `cbrealloc'. */ #define CB_REALLOC(CB_ptr, CB_size) \ (((CB_ptr) = realloc((CB_ptr), (CB_size))) ? (CB_ptr) : cbmyfatal("out of memory")) /* Alias of `cbmemdup'. However, `size' should not be negative. */ #define CB_MEMDUP(CB_res, CB_ptr, CB_size) \ do { \ CB_MALLOC((CB_res), (CB_size) + 1); \ memcpy((CB_res), (CB_ptr), (CB_size)); \ (CB_res)[(CB_size)] = '\0'; \ } while(FALSE) /* Get the size of padding bytes for pointer alignment. `hsiz' specifies the header size of the object. The return value is the size of padding bytes. */ #define CB_ALIGNPAD(CB_hsiz) \ (((CB_hsiz | ~-(int)sizeof(void *)) + 1) - CB_hsiz) /* Alias of `cbdatumopen'. However, no dafault data is specified. */ #define CB_DATUMOPEN(CB_datum) \ do { \ CB_MALLOC((CB_datum), sizeof(*(CB_datum))); \ CB_MALLOC((CB_datum)->dptr, CB_DATUMUNIT); \ (CB_datum)->dptr[0] = '\0'; \ (CB_datum)->dsize = 0; \ (CB_datum)->asize = CB_DATUMUNIT; \ } while(FALSE) /* Alias of `cbdatumopen'. However, `size' should not be negative. */ #define CB_DATUMOPEN2(CB_datum, CB_ptr, CB_size) \ do { \ CB_DATUMOPEN((CB_datum)); \ CB_DATUMCAT((CB_datum), (CB_ptr), (CB_size)); \ } while(FALSE) /* Alias of `cbdatumclose'. */ #define CB_DATUMCLOSE(CB_datum) \ do { \ free((CB_datum)->dptr); \ free((CB_datum)); \ } while(FALSE) /* Alias of `cbdatumcat'. However, `size' should not be negative. */ #define CB_DATUMCAT(CB_datum, CB_ptr, CB_size) \ do { \ if((CB_datum)->dsize + (CB_size) >= (CB_datum)->asize){ \ (CB_datum)->asize = (CB_datum)->asize * 2 + (CB_size) + 1; \ CB_REALLOC((CB_datum)->dptr, (CB_datum)->asize); \ } \ memcpy((CB_datum)->dptr + (CB_datum)->dsize, (CB_ptr), (CB_size)); \ (CB_datum)->dsize += (CB_size); \ (CB_datum)->dptr[(CB_datum)->dsize] = '\0'; \ } while(FALSE) /* Alias of `cbdatumptr'. */ #define CB_DATUMPTR(CB_datum) ((const char *)((CB_datum)->dptr)) /* Alias of `cbdatumsize'. */ #define CB_DATUMSIZE(CB_datum) ((int)((CB_datum)->dsize)) /* Alias of `cbdatumsetsize'. */ #define CB_DATUMSETSIZE(CB_datum, CB_size) \ do { \ if((CB_size) <= (CB_datum)->dsize){ \ (CB_datum)->dsize = (CB_size); \ (CB_datum)->dptr[(CB_size)] = '\0'; \ } else { \ if((CB_size) >= (CB_datum)->asize){ \ (CB_datum)->asize = (CB_datum)->asize * 2 + (CB_size) + 1; \ CB_REALLOC((CB_datum)->dptr, (CB_datum)->asize); \ } \ memset((CB_datum)->dptr + (CB_datum)->dsize, 0, ((CB_size) - (CB_datum)->dsize) + 1); \ (CB_datum)->dsize = (CB_size); \ } \ } while(FALSE) /* Alias of `cbdatumtomalloc'. */ #define CB_DATUMTOMALLOC(CB_datum, CB_ptr, CB_size) \ do { \ (CB_ptr) = (CB_datum)->dptr; \ (CB_size) = (CB_datum)->dsize; \ free((CB_datum)); \ } while(FALSE) /* Alias of `cblistopen'. */ #define CB_LISTOPEN(CB_list) \ do { \ CB_MALLOC((CB_list), sizeof(*(CB_list))); \ (CB_list)->anum = CB_LISTUNIT; \ CB_MALLOC((CB_list)->array, sizeof((CB_list)->array[0]) * (CB_list)->anum); \ (CB_list)->start = 0; \ (CB_list)->num = 0; \ } while(FALSE) /* Alias of `cblistopen'. However, `anum' is specified for the number of initial allocated elements. */ #define CB_LISTOPEN2(CB_list, CB_anum) \ do { \ CB_MALLOC((CB_list), sizeof(*(CB_list))); \ (CB_list)->anum = (CB_anum) > 4 ? (CB_anum) : 4; \ CB_MALLOC((CB_list)->array, sizeof((CB_list)->array[0]) * (CB_list)->anum); \ (CB_list)->start = 0; \ (CB_list)->num = 0; \ } while(FALSE) /* Alias of `cblistclose'. */ #define CB_LISTCLOSE(CB_list) \ do { \ int _CB_i, _CB_end; \ _CB_end = (CB_list)->start + (CB_list)->num; \ for(_CB_i = (CB_list)->start; _CB_i < _CB_end; _CB_i++){ \ free((CB_list)->array[_CB_i].dptr); \ } \ free((CB_list)->array); \ free((CB_list)); \ } while(FALSE) /* Alias of `cblistnum'. */ #define CB_LISTNUM(CB_list) \ ((int)((CB_list)->num)) /* Alias of `cblistval'. However, `sp' is ignored. */ #define CB_LISTVAL(CB_list, CB_index) \ ((const char *)((CB_list)->array[(CB_list)->start+(CB_index)].dptr)) /* Alias of `cblistval'. However, `size' is used instead of `sp'. */ #define CB_LISTVAL2(CB_list, CB_index, CB_size) \ ((CB_size) = (CB_list)->array[(CB_list)->start+(CB_index)].dsize, \ (const char *)((CB_list)->array[(CB_list)->start+(CB_index)].dptr)) /* Alias of `cblistpush'. However, `size' should not be negative. */ #define CB_LISTPUSH(CB_list, CB_ptr, CB_size) \ do { \ int _CB_index; \ _CB_index = (CB_list)->start + (CB_list)->num; \ if(_CB_index >= (CB_list)->anum){ \ (CB_list)->anum *= 2; \ CB_REALLOC((CB_list)->array, (CB_list)->anum * sizeof((CB_list)->array[0])); \ } \ CB_MALLOC((CB_list)->array[_CB_index].dptr, \ ((CB_size) < CB_DATUMUNIT ? CB_DATUMUNIT : (CB_size)) + 1); \ memcpy((CB_list)->array[_CB_index].dptr, (CB_ptr), (CB_size)); \ (CB_list)->array[_CB_index].dptr[(CB_size)] = '\0'; \ (CB_list)->array[_CB_index].dsize = (CB_size); \ (CB_list)->num++; \ } while(FALSE) /* Remove and free an element of the end of a list. `list' specifies a list handle. */ #define CB_LISTDROP(CB_list) \ do { \ if((CB_list)->num > 0){ \ free((CB_list)->array[(CB_list)->start+(CB_list)->num-1].dptr); \ (CB_list)->num--; \ } \ } while(FALSE) /* Alias of `cblistinsert'. However, `index' is not checked and `size' should not be negative. */ #define CB_LISTINSERT(CB_list, CB_index, CB_ptr, CB_size) \ do { \ int _CB_index = (CB_index); \ _CB_index += (CB_list)->start; \ if((CB_list)->start + (CB_list)->num >= (CB_list)->anum){ \ (CB_list)->anum *= 2; \ CB_REALLOC((CB_list)->array, (CB_list)->anum * sizeof((CB_list)->array[0])); \ } \ memmove((CB_list)->array + _CB_index + 1, (CB_list)->array + _CB_index, \ sizeof((CB_list)->array[0]) * ((CB_list)->start + (CB_list)->num - _CB_index)); \ CB_MEMDUP((CB_list)->array[_CB_index].dptr, (CB_ptr), (CB_size)); \ (CB_list)->array[_CB_index].dsize = (CB_size); \ (CB_list)->num++; \ } while(FALSE) /* Alias of `cblistpushbuf'. */ #define CB_LISTPUSHBUF(CB_list, CB_ptr, CB_size) \ do{ \ int _CB_index; \ _CB_index = (CB_list)->start + (CB_list)->num; \ if(_CB_index >= (CB_list)->anum){ \ (CB_list)->anum *= 2; \ CB_REALLOC((CB_list)->array, (CB_list)->anum * sizeof((CB_list)->array[0])); \ } \ (CB_list)->array[_CB_index].dptr = (CB_ptr); \ (CB_list)->array[_CB_index].dsize = (CB_size); \ (CB_list)->num++; \ } while(FALSE) \ /* Alias of `cbmapiterval'. However, `size' is used instead of `sp'. */ #define CB_MAPITERVAL(CB_vbuf, CB_kbuf, CB_vsiz) \ do { \ CBMAPDATUM *_CB_datum; \ _CB_datum = (CBMAPDATUM *)((CB_kbuf) - sizeof(*_CB_datum)); \ (CB_vsiz) = _CB_datum->vsiz; \ (CB_vbuf) = (char *)_CB_datum + sizeof(*_CB_datum) + \ _CB_datum->ksiz + CB_ALIGNPAD(_CB_datum->ksiz); \ } while(FALSE) #undef MYEXTERN #if defined(__cplusplus) /* export for C++ */ } #endif #endif /* duplication check */ /* END OF FILE */ qdbm-1.8.78/README0000644000175000017500000000237011426306503012426 0ustar mikiomikio================================================================ QDBM: Quick Database Manager Copyright (C) 2000-2007 Mikio Hirabayashi ================================================================ Please read the following documents with a WWW browser. How to install QDBM is explained in the specification. README - this file COPYING - license ChangeLog - history of enhancement NEWS - news for users THANKS - list of contributors doc/index.html - index of documents Contents of the directory tree is below. ./ - sources of QDBM ./doc/ - documents ./plus/ - API for C++ ./java/ - API for Java ./perl/ - API for Perl ./ruby/ - API for Ruby ./cgi/ - CGI scripts ./man1/ - manual pages for commands ./man3/ - manual pages for C API ./lab/ - for test and experiment ./bros/ - for comparison with other database managers ./misc/ - miscellaneous files QDBM is released under the terms of the GNU Lesser General Public License. See the file `COPYING' for details. QDBM was written by Mikio Hirabayashi. You can contact the author by e-mail to `mikio@fallabs.com'. Thanks. == END OF FILE == qdbm-1.8.78/dptsv.c0000644000175000017500000001430710610627747013067 0ustar mikiomikio/************************************************************************************************* * Mutual converter between a database of Depot and a TSV text * Copyright (C) 2000-2007 Mikio Hirabayashi * This file is part of QDBM, Quick Database Manager. * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU * Lesser General Public License as published by the Free Software Foundation; either version * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * You should have received a copy of the GNU Lesser General Public License along with QDBM; if * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. *************************************************************************************************/ #include #include #include #include #include #undef TRUE #define TRUE 1 /* boolean true */ #undef FALSE #define FALSE 0 /* boolean false */ /* for RISC OS */ #if defined(__riscos__) || defined(__riscos) #include int __riscosify_control = __RISCOSIFY_NO_PROCESS; #endif /* global variables */ const char *progname; /* program name */ /* function prototypes */ int main(int argc, char **argv); void usage(void); int runimport(int argc, char **argv); int runexport(int argc, char **argv); void pdperror(const char *name); char *getl(void); int doimport(const char *name, int bnum, int bin); int doexport(const char *name, int bin); /* main routine */ int main(int argc, char **argv){ int rv; cbstdiobin(); progname = argv[0]; if(argc < 2) usage(); rv = 0; if(!strcmp(argv[1], "import")){ rv = runimport(argc, argv); } else if(!strcmp(argv[1], "export")){ rv = runexport(argc, argv); } else { usage(); } return rv; } /* print the usage and exit */ void usage(void){ fprintf(stderr, "%s: mutual converter between TSV and Depot database\n", progname); fprintf(stderr, "\n"); fprintf(stderr, "usage:\n"); fprintf(stderr, " %s import [-bnum num] [-bin] name\n", progname); fprintf(stderr, " %s export [-bin] name\n", progname); fprintf(stderr, "\n"); exit(1); } /* parse arguments of import command */ int runimport(int argc, char **argv){ char *name; int i, bnum, bin, rv; name = NULL; bnum = -1; bin = FALSE; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ if(!strcmp(argv[i], "-bnum")){ if(++i >= argc) usage(); bnum = atoi(argv[i]); } else if(!strcmp(argv[i], "-bin")){ bin = TRUE; } else { usage(); } } else if(!name){ name = argv[i]; } else { usage(); } } if(!name) usage(); rv = doimport(name, bnum, bin); return rv; } /* parse arguments of export command */ int runexport(int argc, char **argv){ char *name; int i, bin, rv; name = NULL; bin = FALSE; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ if(!strcmp(argv[i], "-bin")){ bin = TRUE; } else { usage(); } } else if(!name){ name = argv[i]; } else { usage(); } } if(!name) usage(); rv = doexport(name, bin); return rv; } /* print an error message */ void pdperror(const char *name){ fprintf(stderr, "%s: %s: %s\n", progname, name, dperrmsg(dpecode)); } /* read a line */ char *getl(void){ char *buf; int c, len, blen; buf = NULL; len = 0; blen = 256; while((c = getchar()) != EOF){ if(blen <= len) blen *= 2; buf = cbrealloc(buf, blen + 1); if(c == '\n') c = '\0'; buf[len++] = c; if(c == '\0') break; } if(!buf) return NULL; buf[len] = '\0'; return buf; } /* perform import command */ int doimport(const char *name, int bnum, int bin){ DEPOT *depot; char *buf, *kbuf, *vbuf, *ktmp, *vtmp; int i, err, ktsiz, vtsiz; /* open a database */ if(!(depot = dpopen(name, DP_OWRITER | DP_OCREAT, bnum))){ pdperror(name); return 1; } /* loop for each line */ err = FALSE; for(i = 1; (buf = getl()) != NULL; i++){ kbuf = buf; if((vbuf = strchr(buf, '\t')) != NULL){ *vbuf = '\0'; vbuf++; /* store a record */ if(bin){ ktmp = cbbasedecode(kbuf, &ktsiz); vtmp = cbbasedecode(vbuf, &vtsiz); if(!dpput(depot, ktmp, ktsiz, vtmp, vtsiz, DP_DOVER)){ pdperror(name); err = TRUE; } free(vtmp); free(ktmp); } else { if(!dpput(depot, kbuf, -1, vbuf, -1, DP_DOVER)){ pdperror(name); err = TRUE; } } } else { fprintf(stderr, "%s: %s: invalid format in line %d\n", progname, name, i); } free(buf); if(err) break; } /* close the database */ if(!dpclose(depot)){ pdperror(name); return 1; } return err ? 1 : 0; } /* perform export command */ int doexport(const char *name, int bin){ DEPOT *depot; char *kbuf, *vbuf, *tmp; int err, ksiz, vsiz; /* open a database */ if(!(depot = dpopen(name, DP_OREADER, -1))){ pdperror(name); return 1; } /* initialize the iterator */ dpiterinit(depot); /* loop for each key */ err = FALSE; while((kbuf = dpiternext(depot, &ksiz)) != NULL){ /* retrieve a value with a key */ if(!(vbuf = dpget(depot, kbuf, ksiz, 0, -1, &vsiz))){ pdperror(name); free(kbuf); err = TRUE; break; } /* output data */ if(bin){ tmp = cbbaseencode(kbuf, ksiz); printf("%s\t", tmp); free(tmp); tmp = cbbaseencode(vbuf, vsiz); printf("%s\n", tmp); free(tmp); } else { printf("%s\t%s\n", kbuf, vbuf); } /* free resources */ free(vbuf); free(kbuf); } /* check whether all records were retrieved */ if(dpecode != DP_ENOITEM){ pdperror(name); err = TRUE; } /* close the database */ if(!dpclose(depot)){ pdperror(name); return 1; } return err ? 1 : 0; } /* END OF FILE */ qdbm-1.8.78/java/0000755000175000017500000000000011426320065012464 5ustar mikiomikioqdbm-1.8.78/java/Villa.java0000644000175000017500000011664710505671733014425 0ustar mikiomikio/************************************************************************************************* * Java API of Villa, the advanced API of QDBM * Copyright (C) 2000-2006 Mikio Hirabayashi * This file is part of QDBM, Quick Database Manager. * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU * Lesser General Public License as published by the Free Software Foundation; either version * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * You should have received a copy of the GNU Lesser General Public License along with QDBM; if * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. *************************************************************************************************/ package qdbm; /** * The Java API of Villa, the advanced API of QDBM. * This class depends on the native library `jqdbm'. */ public class Villa implements ADBM { //---------------------------------------------------------------- // error codes //---------------------------------------------------------------- /** error code: no error */ public static final int ENOERR = 0; /** error code: with fatal error */ public static final int EFATAL = 1; /** error code: invalid mode */ public static final int EMODE = 2; /** error code: broken database file */ public static final int EBROKEN = 3; /** error code: existing record */ public static final int EKEEP = 4; /** error code: no item found */ public static final int ENOITEM = 5; /** error code: memory allocation error */ public static final int EALLOC = 6; /** error code: memory mapping error */ public static final int EMAP = 7; /** error code: open error */ public static final int EOPEN = 8; /** error code: close error */ public static final int ECLOSE = 9; /** error code: trunc error */ public static final int ETRUNC = 10; /** error code: sync error */ public static final int ESYNC = 11; /** error code: stat error */ public static final int ESTAT = 12; /** error code: seek error */ public static final int ESEEK = 13; /** error code: read error */ public static final int EREAD = 14; /** error code: write error */ public static final int EWRITE = 15; /** error code: lock error */ public static final int ELOCK = 16; /** error code: unlink error */ public static final int EUNLINK = 17; /** error code: mkdir error */ public static final int EMKDIR = 18; /** error code: rmdir error */ public static final int ERMDIR = 19; /** error code: miscellaneous error */ public static final int EMISC = 20; //---------------------------------------------------------------- // open modes //---------------------------------------------------------------- /** open mode: open as a reader */ public static final int OREADER = 1 << 0; /** open mode: open as a writer */ public static final int OWRITER = 1 << 1; /** open mode: writer creating */ public static final int OCREAT = 1 << 2; /** open mode: writer truncating */ public static final int OTRUNC = 1 << 3; /** open mode: open without locking */ public static final int ONOLCK = 1 << 4; /** open mode: lock without blocking */ public static final int OLCKNB = 1 << 5; /** open mode: compress leaves with ZLIB */ public static final int OZCOMP = 1 << 6; /** open mode: compress leaves with LZO */ public static final int OYCOMP = 1 << 7; /** open mode: compress leaves with BZIP2 */ public static final int OXCOMP = 1 << 8; //---------------------------------------------------------------- // comparing modes //---------------------------------------------------------------- /** comparing mode: compare by lexical order */ public static final int CMPLEX = 0; /** comparing mode: compare as long integers */ public static final int CMPNUM = 1; /** comparing mode: compare as decimal strings */ public static final int CMPDEC = 2; /** comparing mode: compare as comparable objects */ public static final int CMPOBJ = 3; //---------------------------------------------------------------- // write modes //---------------------------------------------------------------- /** write mode: overwrite the existing value */ public static final int DOVER = 0; /** write mode: keep the existing value */ public static final int DKEEP = 1; /** write mode: concatenate values */ public static final int DCAT = 2; /** write mode: allow duplication of records */ public static final int DDUP = 3; /** write mode: allow duplication with reverse order */ public static final int DDUPR = 4; //---------------------------------------------------------------- // jump modes //---------------------------------------------------------------- /** jump mode: jump mode: step forward */ public static final int JFORWARD = 0; /** jump mode: jump mode: step backward */ public static final int JBACKWARD = 1; /** insertion mode: overwrite the current record */ public static final int CPCURRENT = 0; /** insertion mode: insert before the current record */ public static final int CPBEFORE = 1; /** insertion mode: insert after the current record */ public static final int CPAFTER = 2; //---------------------------------------------------------------- // static initializer //---------------------------------------------------------------- static { try { System.loadLibrary("jqdbm"); } catch(UnsatisfiedLinkError e){ e.printStackTrace(); } vlinit(); } //---------------------------------------------------------------- // public static methods //---------------------------------------------------------------- /** * Get the version information. * @return the string of the version information. */ public static synchronized String version(){ return vlversion(); } /** * Get an error message. * @param ecode an error code. * @return the message string of the error code. */ public static synchronized String errmsg(int ecode){ return vlerrmsg(ecode); } /** * Remove a database file. * @param name the name of a database file. * @throws VillaException if an error occurs. */ public static void remove(String name) throws VillaException { synchronized(ADBM.class){ if(vlremove(name) == 0) throw new VillaException(vlecode()); } } //---------------------------------------------------------------- // instance fields //---------------------------------------------------------------- /** Whether to repress frequent exceptions. */ public boolean silent; /** Index of the native table for database handles. */ private int index; /** Whether the handle has the transaction or not. */ private boolean tran; /** Monitor for mutual exclusion control. */ private Object tranmonitor; //---------------------------------------------------------------- // public or protected methods //---------------------------------------------------------------- /** * Get the database handle. * @param name the name of a database file. * @param omode the connection mode: `Villa.OWRITER' as a writer, `Villa.OREADER' as * a reader. If the mode is `Villa.OWRITER', the following may be added by bitwise or: * `Villa.OCREAT', which means it creates a new database if not exist, `Villa.OTRUNC', * which means it creates a new database regardless if one exists, `Villa.OZCOMP', which means * leaves in the database are compressed with ZLIB, `Villa.OYCOMP', which means leaves in the * database are compressed with LZO, `Villa.OXCOMP', which means leaves in the database are * compressed with BZIP2. Both of `Villa.OREADER' and `Villa.OWRITER' can be added to by * bitwise or: `Villa.ONOLCK', which means it opens a database file without file locking, or * `Villa.OLCKNB', which means locking is performed without blocking. * @param cmode the comparing function: `Villa.CMPLEX' comparing keys in lexical order, * `Villa.CMPNUM' comparing keys as numbers of big endian, `Villa.CMPDEC' comparing keys as * decimal strings, `Villa.CMPOBJ' comparing keys as serialized objects implementing * `java.util.Comparable'. The comparing function should be kept same in the life of a * database. * @note While connecting as a writer, an exclusive lock is invoked to the database file. * While connecting as a reader, a shared lock is invoked to the database file. The thread * blocks until the lock is achieved. `Villa.OZCOMP', `Villa.OYCOMP', and `Villa.OXCOMP' are * available only if QDBM was built each with ZLIB, LZO, and BZIP2 enabled. If `Villa.ONOLCK' * is used, the application is responsible for exclusion control. */ public Villa(String name, int omode, int cmode) throws VillaException { synchronized(ADBM.class){ silent = false; if((index = vlopen(name, omode, cmode)) == -1) throw new VillaException(vlecode()); } tran = false; tranmonitor = new Object(); } /** * Get the database handle as a reader. * The same as `Villa(name, Villa.OREADER, Villa.CMPLEX)'. * @see #Villa(java.lang.String, int, int) */ public Villa(String name) throws VillaException { this(name, OREADER, CMPLEX); } /** * Release the resources. * @note If the database handle is not closed yet, it is closed. Every database should be * closed explicitly. Do not cast the duty on the gerbage collection. */ protected void finalize() throws Throwable { try { if(index < 0) return; synchronized(ADBM.class){ vlclose(index); index = -1; } } finally { super.finalize(); } } /** * Close the database handle. * @throws VillaException if an error occurs. * @note Updating a database is assured to be written when the handle is closed. If a * writer opens a database but does not close it appropriately, the database will be broken. * If the transaction is activated and not committed, it is aborted. */ public void close() throws VillaException { if(index < 0) throw new VillaException(); synchronized(ADBM.class){ int rv = vlclose(index); index = -1; if(rv == 0) throw new VillaException(vlecode()); } } /** * Store a record. * @param key a byte array of a key. * @param val a byte array of a value. * @param dmode behavior when the key overlaps, by the following values: `Villa.DOVER', * which means the specified value overwrites the existing one, `Villa.DKEEP', which means * the existing value is kept, `Villa.DCAT', which means the specified value is concatenated * at the end of the existing value, `Villa.DDUP', which means duplication of keys is allowed * and the specified value is added as the last one, `Villa.DDUPR', which means duplication of * keys is allowed and the specified value is added as the first one. * @return always true. However, if the silent flag is true and replace is cancelled, false is * returned instead of exception. * @throws VillaException if an error occurs or replace is cancelled. * @note The cursor becomes unavailable due to updating database. */ public boolean put(byte[] key, byte[] val, int dmode) throws VillaException { if(index < 0) throw new VillaException(); synchronized(ADBM.class){ if(vlput(index, key, key.length, val, val.length, dmode) == 0){ if(silent && vlecode() == EKEEP) return false; throw new VillaException(vlecode()); } return true; } } /** * Store a record with overwrite. * The same as `put(key, val, Villa.DOVER)'. * @see #put(byte[], byte[], int) */ public boolean put(byte[] key, byte[] val) throws VillaException { return put(key, val, DOVER); } /** * Store a record composed of serializable objects. * The same as `put(qdbm.Util.serialize(key), qdbm.Util.serialize(val), dmode)'. * @see #put(byte[], byte[], int) * @note If serialization is failed, an instance of `VillaException' is thrown. */ public boolean putobj(Object key, Object val, int dmode) throws VillaException { byte[] kbuf = Util.serialize(key); byte[] vbuf = Util.serialize(val); if(kbuf == null || vbuf == null) throw new VillaException(); return put(kbuf, vbuf, dmode); } /** * Delete a record. * @param key a byte array of a key. * @return always true. However, if the silent flag is true and no record corresponds, false * is returned instead of exception. * @throws VillaException if an error occurs or no record corresponds. * @note When the key of duplicated records is specified, the first record of the same key * is deleted. The cursor becomes unavailable due to updating database. */ public boolean out(byte[] key) throws VillaException { if(index < 0) throw new VillaException(); synchronized(ADBM.class){ if(vlout(index, key, key.length) == 0){ if(silent && vlecode() == ENOITEM) return false; throw new VillaException(vlecode()); } return true; } } /** * Delete a record composed of serializable objects. * The same as `out(qdbm.Util.serialize(key))'. * @see #out(byte[]) * @note If serialization is failed, an instance of `VillaException' is thrown. */ public boolean outobj(Object key) throws VillaException { byte[] kbuf = Util.serialize(key); if(kbuf == null) throw new VillaException(); return out(kbuf); } /** * Retrieve a record. * @param key a byte array of a key. * @return a byte array of the value of the corresponding record. If the silent flag is true * and no record corresponds, `null' is returned instead of exception. * @throws VillaException if an error occurs, no record corresponds. * @note When the key of duplicated records is specified, the value of the first record of * the same key is selected. */ public byte[] get(byte[] key) throws VillaException { if(index < 0) throw new VillaException(); synchronized(ADBM.class){ byte[] val = vlget(index, key, key.length); if(val == null){ if(silent && vlecode() == ENOITEM) return null; throw new VillaException(vlecode()); } return val; } } /** * Retrieve a record composed of serializable objects. * The same as `qdbm.Util.deserialize(get(qdbm.Util.serialize(key)))'. * @see #get(byte[]) * @note If serialization is failed, an instance of `VillaException' is thrown. */ public Object getobj(Object key) throws VillaException { byte[] kbuf = Util.serialize(key); if(kbuf == null) throw new VillaException(); byte[] vbuf = get(kbuf); if(vbuf == null) return null; Object val = Util.deserialize(vbuf); if(val == null) throw new VillaException(); return val; } /** * Get the size of the value of a record. * @param key a byte array of a key. * @return the size of the value of the corresponding record. If multiple records correspond, * the size of the first is returned. If the silent flag is true and no record corresponds, -1 * is returned instead of exception. * @throws VillaException if an error occurs. */ public int vsiz(byte[] key) throws VillaException { if(index < 0) throw new VillaException(); synchronized(ADBM.class){ int rv = vlvsiz(index, key, key.length); if(rv == -1){ if(silent && vlecode() == ENOITEM) return -1; throw new VillaException(vlecode()); } return rv; } } /** * Get the size of the value of a record, composed of serializable objects. * The same as `vsiz(qdbm.Util.serialize(key))'. * @see #vnum(byte[]) * @note If serialization is failed, an instance of `VillaException' is thrown. */ public int vsizobj(Object key) throws VillaException { byte[] kbuf = Util.serialize(key); if(kbuf == null) throw new VillaException(); return vsiz(kbuf); } /** * Get the number of records corresponding a key. * @param key a byte array of a key. * @return the number of corresponding records. If no record corresponds, 0 is returned. * @throws VillaException if an error occurs. */ public int vnum(byte[] key) throws VillaException { if(index < 0) throw new VillaException(); synchronized(ADBM.class){ int rv = vlvnum(index, key, key.length); if(rv == -1) throw new VillaException(vlecode()); return rv; } } /** * Get the number of records corresponding a key, composed of serializable objects. * The same as `vnum(qdbm.Util.serialize(key))'. * @see #vnum(byte[]) * @note If serialization is failed, an instance of `VillaException' is thrown. */ public int vnumobj(Object key) throws VillaException { byte[] kbuf = Util.serialize(key); if(kbuf == null) throw new VillaException(); return vnum(kbuf); } /** * Move the cursor to the first record. * @return always true. However, if the silent flag is true and no record corresponds, false * is returned instead of exception. * @throws VillaException if an error occurs or there is no record in the database. */ public boolean curfirst() throws VillaException { if(index < 0) throw new VillaException(); synchronized(ADBM.class){ if(vlcurfirst(index) == 0){ if(silent && vlecode() == ENOITEM) return false; throw new VillaException(vlecode()); } return true; } } /** * Move the cursor to the last record. * @return always true. However, if the silent flag is true and no record corresponds, false * is returned instead of exception. * @throws VillaException if an error occurs or there is no record in the database. */ public boolean curlast() throws VillaException { if(index < 0) throw new VillaException(); synchronized(ADBM.class){ if(vlcurlast(index) == 0){ if(silent && vlecode() == ENOITEM) return false; throw new VillaException(vlecode()); } return true; } } /** * Move the cursor to the next record. * @return always true. However, if the silent flag is true and no record corresponds, false * is returned instead of exception. * @throws VillaException if an error occurs or there is no previous record. */ public boolean curprev() throws VillaException { if(index < 0) throw new VillaException(); synchronized(ADBM.class){ if(vlcurprev(index) == 0){ if(silent && vlecode() == ENOITEM) return false; throw new VillaException(vlecode()); } return true; } } /** * Move the cursor to the next record. * @return always true. However, if the silent flag is true and no record corresponds, false * is returned instead of exception. * @throws VillaException if an error occurs or there is no next record. */ public boolean curnext() throws VillaException { if(index < 0) throw new VillaException(); synchronized(ADBM.class){ if(vlcurnext(index) == 0){ if(silent && vlecode() == ENOITEM) return false; throw new VillaException(vlecode()); } return true; } } /** * Move the cursor to a position around a record. * @param key a byte array of a key. * @param jmode detail adjustment: `Villa.JFORWARD', which means that the cursor is set to * the first record of the same key and that the cursor is set to the next substitute if * completely matching record does not exist, `Villa.JBACKWARD', which means that the cursor * is set to the last record of the same key and that the cursor is set to the previous * substitute if completely matching record does not exist. * @return always true. However, if the silent flag is true and no record corresponds, false * is returned instead of exception. * @throws VillaException if an error occurs or there is no record corresponding the condition. */ public boolean curjump(byte[] key, int jmode) throws VillaException { if(index < 0) throw new VillaException(); synchronized(ADBM.class){ if(vlcurjump(index, key, key.length, jmode) == 0){ if(silent && vlecode() == ENOITEM) return false; throw new VillaException(vlecode()); } return true; } } /** * Move the cursor to a position around a record for stepping forward. * The same as `curjump(key, Villa.JFORFARD)'. * @see #curjump(byte[], int) */ public boolean curjump(byte[] key) throws VillaException { return curjump(key, JFORWARD); } /** * Move the cursor to a position around a record composed of serializable objects. * The same as `curjump(qdbm.Util.serialize(key), jmode)'. * @see #curjump(byte[], int) * @note If serialization is failed, an instance of `VillaException' is thrown. */ public boolean curjumpobj(Object key, int jmode) throws VillaException { byte[] kbuf = Util.serialize(key); if(kbuf == null) throw new VillaException(); return curjump(kbuf, jmode); } /** * Get the key of the record where the cursor is. * @return a byte array of the key of the corresponding record. If the silent flag is true and * no record corresponds, `null' is returned instead of exception. * @throws VillaException if an error occurs or no record corresponds to the cursor. */ public byte[] curkey() throws VillaException { if(index < 0) throw new VillaException(); synchronized(ADBM.class){ byte[] val = vlcurkey(index); if(val == null){ if(silent && vlecode() == ENOITEM) return null; throw new VillaException(vlecode()); } return val; } } /** * Get the key of the record composed of serializable objects, where the cursor is. * The same as `qdbm.Util.deserialize(curkey())'. * @see #curkey() * @note If serialization is failed, an instance of `VillaException' is thrown. */ public Object curkeyobj() throws VillaException { byte[] kbuf = curkey(); if(kbuf == null) return null; Object key = Util.deserialize(kbuf); if(key == null) throw new VillaException(); return key; } /** * Get the value of the record where the cursor is. * @return a byte array of the value of the corresponding record. If the silent flag is true * and no record corresponds, `null' is returned instead of exception. * @throws VillaException if an error occurs or no record corresponds to the cursor. */ public byte[] curval() throws VillaException { if(index < 0) throw new VillaException(); synchronized(ADBM.class){ byte[] val = vlcurval(index); if(val == null){ if(silent && vlecode() == ENOITEM) return null; throw new VillaException(vlecode()); } return val; } } /** * Get the value of the record where the cursor is. * The same as `qdbm.Util.deserialize(curval())'. * @see #curval() * @note If serialization is failed, an instance of `VillaException' is thrown. */ public Object curvalobj() throws VillaException { byte[] vbuf = curval(); if(vbuf == null) return null; Object val = Util.deserialize(vbuf); if(val == null) throw new VillaException(); return val; } /** * Insert a record around the cursor. * @param val a byte array of a value. * @param cpmode detail adjustment: `Villa.CPCURRENT', which means that the value of the * current record is overwritten, `Villa.CPBEFORE', which means that a new record is inserted * before the current record, `Villa.CPAFTER', which means that a new record is inserted after * the current record. * @return always true. However, if the silent flag is true and no record corresponds to the * cursor, false is returned instead of exception. * @throws VillaException if an error occurs or no record corresponds to the cursor. * @note After insertion, the cursor is moved to the inserted record. */ public boolean curput(byte[] val, int cpmode) throws VillaException { if(index < 0) throw new VillaException(); synchronized(ADBM.class){ if(vlcurput(index, val, val.length, cpmode) == 0){ if(silent && vlecode() == ENOITEM) return false; throw new VillaException(vlecode()); } return true; } } /** * Insert a record as the successor of the cursor. * The same as `curput(val, Villa.CPCURRENT)'. * @see #curput(byte[], int) */ public boolean curput(byte[] val) throws VillaException { return curput(val, CPCURRENT); } /** * Insert a record around the cursor. * The same as `curput(qdbm.Util.serialize(val), cpmode)'. * @see #curput(byte[], int) */ public boolean curputobj(Object val, int cpmode) throws VillaException { byte[] vbuf = Util.serialize(val); if(vbuf == null) throw new VillaException(); return curput(vbuf, cpmode); } /** * Delete the record where the cursor is. * @return always true. However, if the silent flag is true and no record corresponds to the * cursor, false is returned instead of exception. * @throws VillaException if an error occurs or no record corresponds to the cursor. * @note After deletion, the cursor is moved to the next record if possible. */ public boolean curout() throws VillaException { if(index < 0) throw new VillaException(); synchronized(ADBM.class){ if(vlcurout(index) == 0){ if(silent && vlecode() == ENOITEM) return false; throw new VillaException(vlecode()); } return true; } } /** * Set the tuning parameters for performance. * @param lrecmax the max number of records in a leaf node of B+ tree. If it is not more * than 0, the default value is specified. * @param nidxmax the max number of indexes in a non-leaf node of B+ tree. If it is not more * than 0, the default value is specified. * @param lcnum the max number of caching leaf nodes. If it is not more than 0, the default * value is specified. * @param ncnum the max number of caching non-leaf nodes. If it is not more than 0, the * default value is specified. * @throws VillaException if an error occurs. * @note The default setting is equivalent to `settuning(49, 192, 1024, 512)'. Because tuning * parameters are not saved in a database, you should specify them every opening a database. */ public void settuning(int lrecmax, int nidxmax, int lcnum, int ncnum) throws VillaException { if(index < 0) throw new VillaException(); synchronized(ADBM.class){ vlsettuning(index, lrecmax, nidxmax, lcnum, ncnum); } } /** * Synchronize updating contents with the file and the device. * @throws VillaException if an error occurs. * @note This method is useful when another process uses the connected database file. This * method should not be used while the transaction is activated. */ public void sync() throws VillaException { if(index < 0) throw new VillaException(); synchronized(ADBM.class){ if(vlsync(index) == 0) throw new VillaException(vlecode()); } } /** * Optimize the database. * @throws VillaException if an error occurs. * @note In an alternating succession of deleting and storing with overwrite or concatenate, * dispensable regions accumulate. This method is useful to do away with them. This method * should not be used while the transaction is activated. */ public void optimize() throws VillaException { if(index < 0) throw new VillaException(); synchronized(ADBM.class){ if(vloptimize(index) == 0) throw new VillaException(vlecode()); } } /** * Get the name of the database. * @return the string of the name of the database. * @throws VillaException if an error occurs. */ public String name() throws VillaException { if(index < 0) throw new VillaException(); synchronized(ADBM.class){ String buf = vlname(index); if(buf == null) throw new VillaException(vlecode()); return buf; } } /** * Get the size of the database file. * @return the size of the database file. * @throws VillaException if an error occurs. * @note Because of the I/O buffer, the return value may be less than the real size. */ public int fsiz() throws VillaException { if(index < 0) throw new VillaException(); synchronized(ADBM.class){ int rv = vlfsiz(index); if(rv == -1) throw new VillaException(vlecode()); return rv; } } /** * Get the number of the leaf nodes of B+ tree. * @return the number of the leaf nodes. * @throws VillaException if an error occurs. */ public int lnum() throws VillaException { if(index < 0) throw new VillaException(); synchronized(ADBM.class){ int rv = vllnum(index); if(rv == -1) throw new VillaException(vlecode()); return rv; } } /** * Get the number of the non-leaf nodes of B+ tree. * @return the number of the non-leaf nodes. * @throws VillaException if an error occurs. */ public int nnum() throws VillaException { if(index < 0) throw new VillaException(); synchronized(ADBM.class){ int rv = vlnnum(index); if(rv == -1) throw new VillaException(vlecode()); return rv; } } /** * Get the number of the records stored in a database. * @return the number of the records stored in the database. * @throws VillaException if an error occurs. */ public int rnum() throws VillaException { if(index < 0) throw new VillaException(); synchronized(ADBM.class){ int rv = vlrnum(index); if(rv == -1) throw new VillaException(vlecode()); return rv; } } /** * Check whether the database handle is a writer or not. * @return true if the handle is a writer, false if not. * @throws VillaException if an error occurs. */ public boolean writable() throws VillaException { if(index < 0) throw new VillaException(); synchronized(ADBM.class){ return vlwritable(index) == 0 ? false : true; } } /** * Check whether the database has a fatal error or not. * @return true if the database has a fatal error, false if not. * @throws VillaException if an error occurs. */ public boolean fatalerror() throws VillaException { if(index < 0) throw new VillaException(); synchronized(ADBM.class){ return vlfatalerror(index) == 0 ? false : true; } } /** * Get the inode number of the database. * @return the inode number of the database file. * @throws VillaException if an error occurs. */ public int inode() throws VillaException { if(index < 0) throw new VillaException(); synchronized(ADBM.class){ return vlinode(index); } } /** * Get the last modified time of the database. * @return the last modified time of the database. * @throws VillaException if an error occurs. */ public long mtime() throws VillaException { if(index < 0) throw new VillaException(); synchronized(ADBM.class){ return vlmtime(index); } } /** * Begin the transaction. * @throws VillaException if an error occurs. * @note If a thread is already in the transaction, the other threads block until the prius * is out of the transaction. Only one transaction can be activated with a database handle * at the same time. */ public void tranbegin() throws VillaException { if(index < 0) throw new VillaException(); synchronized(tranmonitor){ while(tran){ try { tranmonitor.wait(); } catch(InterruptedException e){ e.printStackTrace(); throw new VillaException(); } } tran = true; } synchronized(ADBM.class){ if(vltranbegin(index) == 0){ tran = false; throw new VillaException(vlecode()); } } } /** * Commit the transaction. * @throws VillaException if an error occurs. * @note Updating a database in the transaction is fixed when it is committed successfully. * Any other thread except for the one which began the transaction should not call this method. */ public void trancommit() throws VillaException { if(index < 0) throw new VillaException(); synchronized(ADBM.class){ if(vltrancommit(index) == 0){ synchronized(tranmonitor){ tran = false; tranmonitor.notify(); } throw new VillaException(vlecode()); } } synchronized(tranmonitor){ tran = false; tranmonitor.notify(); } } /** * Abort the transaction. * @throws VillaException if an error occurs. * @note Updating a database in the transaction is discarded when it is aborted. The state * of the database is rollbacked to before transaction. Any other thread except for the one * which began the transaction should not call this method. */ public void tranabort() throws VillaException { if(index < 0) throw new VillaException(); synchronized(ADBM.class){ if(vltranabort(index) == 0){ synchronized(tranmonitor){ tran = false; tranmonitor.notify(); } throw new VillaException(vlecode()); } } synchronized(tranmonitor){ tran = false; tranmonitor.notify(); } } /** * Store a record. * @param key a byte array of a key. * @param val a byte array of a value. * @param replace whether the existing value is to be overwritten or not. * @throws VillaException if an error occurs or replace is cancelled. */ public void store(byte[] key, byte[] val, boolean replace) throws VillaException { if(!put(key, val, replace ? DOVER : DKEEP)) throw new VillaException(EKEEP); } /** * Delete a record. * @param key a byte array of a key. * @throws VillaException if an error occurs or no record corresponds. */ public void delete(byte[] key) throws VillaException { if(!out(key)) throw new VillaException(ENOITEM); } /** * Fetch a record. * @param key a byte array of a key. * @return a byte array of the value of the corresponding record. * @throws VillaException if an error occurs or no record corresponds. */ public byte[] fetch(byte[] key) throws VillaException { byte[] vbuf = get(key); if(vbuf == null) throw new VillaException(ENOITEM); return vbuf; } /** * Get the first key. * @return a byte array of the key of the first record. * @throws VillaException if an error occurs or no record corresponds. */ public byte[] firstkey() throws VillaException { curfirst(); byte[] kbuf = curkey(); if(kbuf == null) throw new VillaException(ENOITEM); return kbuf; } /** * Get the next key. * @return a byte array of the key of the next record. * @throws VillaException if an error occurs or no record corresponds. */ public byte[] nextkey() throws VillaException { curnext(); byte[] kbuf = curkey(); if(kbuf == null) throw new VillaException(ENOITEM); return kbuf; } /** * Check whether a fatal error occured or not. * @return true if the database has a fatal error, false if not. * @throws VillaException if an error occurs. */ public boolean error() throws VillaException { return fatalerror(); } /** * Get a multiple cursor. * @return a multiple cursor. * @note Even if plural cursors are fetched out of a database handle, they does not share the * locations with each other. Note that this method can be used only if the database handle * is connected as a reader. */ public VillaCursor mulcuropen() throws VillaException { return new VillaCursor(this); } //---------------------------------------------------------------- // friendly methods //---------------------------------------------------------------- /** * Get the index of the native table for database handles. * @return the index of the native table for database handles. */ public int getindex(){ return index; } //---------------------------------------------------------------- // private static methods //---------------------------------------------------------------- /** * Compare keys of two records as serialized objects implementing `java.util.Comparable'. * @param abuf serialized data of one object. * @param bbuf serialized data of the other object. * @return positive if the former is big, negative if the latter is big, 0 if both are * equivalent. */ private static final int objcompare(byte[] abuf, byte[] bbuf){ Object a = Util.deserialize(abuf); Object b = Util.deserialize(bbuf); if(a != null && b == null) return 1; if(a == null && b != null) return -1; if(a == null && b == null) return 0; try { return ((Comparable)a).compareTo(b); } catch(ClassCastException e){ return 0; } } //---------------------------------------------------------------- // native methods //---------------------------------------------------------------- private static synchronized final native void vlinit(); private static synchronized final native String vlversion(); private static synchronized final native int vlecode(); private static synchronized final native String vlerrmsg(int ecode); private static synchronized final native int vlopen(String name, int omode, int cmode); private static synchronized final native int vlclose(int index); private static synchronized final native int vlput(int index, byte[] key, int ksiz, byte[] val, int vsiz, int dmode); private static synchronized final native int vlout(int index, byte[] key, int ksiz); private static synchronized final native byte[] vlget(int index, byte[] key, int ksiz); private static synchronized final native int vlvsiz(int index, byte[] key, int ksiz); private static synchronized final native int vlvnum(int index, byte[] key, int ksiz); private static synchronized final native int vlcurfirst(int index); private static synchronized final native int vlcurlast(int index); private static synchronized final native int vlcurprev(int index); private static synchronized final native int vlcurnext(int index); private static synchronized final native int vlcurjump(int index, byte[] key, int ksiz, int jmode); private static synchronized final native byte[] vlcurkey(int index); private static synchronized final native byte[] vlcurval(int index); private static synchronized final native int vlcurput(int index, byte[] val, int vsiz, int cpmode); private static synchronized final native int vlcurout(int index); private static synchronized final native void vlsettuning(int index, int lrecmax, int nidxmax, int lcnum, int ncnum); private static synchronized final native int vlsync(int index); private static synchronized final native int vloptimize(int index); private static synchronized final native String vlname(int index); private static synchronized final native int vlfsiz(int index); private static synchronized final native int vllnum(int index); private static synchronized final native int vlnnum(int index); private static synchronized final native int vlrnum(int index); private static synchronized final native int vlwritable(int index); private static synchronized final native int vlfatalerror(int index); private static synchronized final native int vlinode(int index); private static synchronized final native long vlmtime(int index); private static synchronized final native int vltranbegin(int index); private static synchronized final native int vltrancommit(int index); private static synchronized final native int vltranabort(int index); private static synchronized final native int vlremove(String name); } /* END OF FILE */ qdbm-1.8.78/java/jdepot.c0000644000175000017500000002445310441455444014133 0ustar mikiomikio/************************************************************************************************* * Implementation of Depot for Java * Copyright (C) 2000-2006 Mikio Hirabayashi * This file is part of QDBM, Quick Database Manager. * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU * Lesser General Public License as published by the Free Software Foundation; either version * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * You should have received a copy of the GNU Lesser General Public License along with QDBM; if * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. *************************************************************************************************/ #include "qdbm_Depot.h" #include #include #include #include #include #define MAXOPEN 1024 DEPOT *dptable[MAXOPEN]; static int getnewindex(void); static int checkdup(const char *name); static int getdpomode(jint omode); static int getdpdmode(jint dmode); /************************************************************************************************* * public objects *************************************************************************************************/ JNIEXPORT void JNICALL Java_qdbm_Depot_dpinit(JNIEnv *env, jclass myclass) { int i; for(i = 0; i < MAXOPEN; i++){ dptable[i] = NULL; } } JNIEXPORT jstring JNICALL Java_qdbm_Depot_dpversion(JNIEnv *env, jclass myclass) { return (*env)->NewStringUTF(env, dpversion); } JNIEXPORT jint JNICALL Java_qdbm_Depot_dpecode(JNIEnv *env, jclass myclass){ switch(dpecode){ case DP_ENOERR: return qdbm_Depot_ENOERR; case DP_EFATAL: return qdbm_Depot_EFATAL; case DP_EMODE: return qdbm_Depot_EMODE; case DP_EBROKEN: return qdbm_Depot_EBROKEN; case DP_EKEEP: return qdbm_Depot_EKEEP; case DP_ENOITEM: return qdbm_Depot_ENOITEM; case DP_EALLOC: return qdbm_Depot_EALLOC; case DP_EMAP: return qdbm_Depot_EMAP; case DP_EOPEN: return qdbm_Depot_EOPEN; case DP_ECLOSE: return qdbm_Depot_ECLOSE; case DP_ETRUNC: return qdbm_Depot_ETRUNC; case DP_ESYNC: return qdbm_Depot_ESYNC; case DP_ESTAT: return qdbm_Depot_ESTAT; case DP_ESEEK: return qdbm_Depot_ESEEK; case DP_EREAD: return qdbm_Depot_EREAD; case DP_EWRITE: return qdbm_Depot_EWRITE; case DP_ELOCK: return qdbm_Depot_ELOCK; case DP_EUNLINK: return qdbm_Depot_EUNLINK; case DP_EMKDIR: return qdbm_Depot_EMKDIR; case DP_ERMDIR: return qdbm_Depot_ERMDIR; case DP_EMISC: return qdbm_Depot_EMISC; } return -1; } JNIEXPORT jstring JNICALL Java_qdbm_Depot_dperrmsg(JNIEnv *env, jclass myclass, jint ecode) { return (*env)->NewStringUTF(env, dperrmsg(ecode)); } JNIEXPORT jint JNICALL Java_qdbm_Depot_dpopen(JNIEnv *env, jclass myclass, jstring name, jint omode, jint bnum) { DEPOT *depot; const char *tname; jboolean ic; int index; if((index = getnewindex()) == -1) return -1; tname = (*env)->GetStringUTFChars(env, name, &ic); if(checkdup(tname) == -1){ if(ic == JNI_TRUE) (*env)->ReleaseStringUTFChars(env, name, tname); dpecode = DP_EMISC; return -1; } depot = dpopen(tname, getdpomode(omode), bnum); if(ic == JNI_TRUE) (*env)->ReleaseStringUTFChars(env, name, tname); if(!depot) return -1; dptable[index] = depot; return index; } JNIEXPORT jint JNICALL Java_qdbm_Depot_dpclose(JNIEnv *env, jclass myclass, jint index) { DEPOT *depot; depot = dptable[index]; dptable[index] = NULL; return dpclose(depot); } JNIEXPORT jint JNICALL Java_qdbm_Depot_dpput(JNIEnv *env, jclass myclass, jint index, jbyteArray key, jint ksiz, jbyteArray val, jint vsiz, jint dmode) { jbyte *kbuf, *vbuf; jboolean ick, icv; int rv; kbuf = (*env)->GetByteArrayElements(env, key, &ick); vbuf = (*env)->GetByteArrayElements(env, val, &icv); rv = dpput(dptable[index], (char *)kbuf, ksiz, (char *)vbuf, vsiz, getdpdmode(dmode)); if(ick == JNI_TRUE) (*env)->ReleaseByteArrayElements(env, key, kbuf, JNI_ABORT); if(icv == JNI_TRUE) (*env)->ReleaseByteArrayElements(env, val, vbuf, JNI_ABORT); return rv; } JNIEXPORT jint JNICALL Java_qdbm_Depot_dpout(JNIEnv *env, jclass myclass, jint index, jbyteArray key, jint ksiz) { jbyte *kbuf; jboolean ick; int rv; kbuf = (*env)->GetByteArrayElements(env, key, &ick); rv = dpout(dptable[index], (char *)kbuf, ksiz); if(ick == JNI_TRUE) (*env)->ReleaseByteArrayElements(env, key, kbuf, JNI_ABORT); return rv; } JNIEXPORT jbyteArray JNICALL Java_qdbm_Depot_dpget(JNIEnv *env, jclass myclass, jint index, jbyteArray key, jint ksiz, jint start, jint max) { jbyte *kbuf; jboolean ick; char *val; int vsiz; jbyteArray vbuf; kbuf = (*env)->GetByteArrayElements(env, key, &ick); val = dpget(dptable[index], (char *)kbuf, ksiz, start, max, &vsiz); if(ick == JNI_TRUE) (*env)->ReleaseByteArrayElements(env, key, kbuf, JNI_ABORT); if(val){ vbuf = (*env)->NewByteArray(env, vsiz); (*env)->SetByteArrayRegion(env, vbuf, 0, vsiz, (jbyte *)val); free(val); } else { vbuf = NULL; } return vbuf; } JNIEXPORT jint JNICALL Java_qdbm_Depot_dpvsiz(JNIEnv *env, jclass myclass, jint index, jbyteArray key, jint ksiz) { jbyte *kbuf; jboolean ick; int rv; kbuf = (*env)->GetByteArrayElements(env, key, &ick); rv = dpvsiz(dptable[index], (char *)kbuf, ksiz); if(ick == JNI_TRUE) (*env)->ReleaseByteArrayElements(env, key, kbuf, JNI_ABORT); return rv; } JNIEXPORT jint JNICALL Java_qdbm_Depot_dpiterinit(JNIEnv *env, jclass myclass, jint index) { return dpiterinit(dptable[index]); } JNIEXPORT jbyteArray JNICALL Java_qdbm_Depot_dpiternext(JNIEnv *env, jclass myclass, jint index) { char *val; int vsiz; jbyteArray vbuf; val = dpiternext(dptable[index], &vsiz); if(val){ vbuf = (*env)->NewByteArray(env, vsiz); (*env)->SetByteArrayRegion(env, vbuf, 0, vsiz, (jbyte *)val); free(val); } else { vbuf = NULL; } return vbuf; } JNIEXPORT jint JNICALL Java_qdbm_Depot_dpsetalign(JNIEnv *env, jclass myclass, jint index, jint align) { return dpsetalign(dptable[index], align); } JNIEXPORT jint JNICALL Java_qdbm_Depot_dpsetfbpsiz(JNIEnv *env, jclass myclass, jint index, jint size) { return dpsetfbpsiz(dptable[index], size); } JNIEXPORT jint JNICALL Java_qdbm_Depot_dpsync(JNIEnv *env, jclass myclass, jint index) { return dpsync(dptable[index]); } JNIEXPORT jint JNICALL Java_qdbm_Depot_dpoptimize(JNIEnv *env, jclass myclass, jint index, jint bnum) { return dpoptimize(dptable[index], bnum); } JNIEXPORT jstring JNICALL Java_qdbm_Depot_dpname(JNIEnv *env, jclass myclass, jint index) { char *name; jstring nbuf; name = dpname(dptable[index]); if(name){ nbuf = (*env)->NewStringUTF(env, name); free(name); } else { nbuf = NULL; } return nbuf; } JNIEXPORT jint JNICALL Java_qdbm_Depot_dpfsiz(JNIEnv *env, jclass myclass, jint index) { return dpfsiz(dptable[index]); } JNIEXPORT jint JNICALL Java_qdbm_Depot_dpbnum(JNIEnv *env, jclass myclass, jint index) { return dpbnum(dptable[index]); } JNIEXPORT jint JNICALL Java_qdbm_Depot_dpbusenum(JNIEnv *env, jclass myclass, jint index) { return dpbusenum(dptable[index]); } JNIEXPORT jint JNICALL Java_qdbm_Depot_dprnum(JNIEnv *env, jclass myclass, jint index) { return dprnum(dptable[index]); } JNIEXPORT jint JNICALL Java_qdbm_Depot_dpwritable(JNIEnv *env, jclass myclass, jint index) { return dpwritable(dptable[index]); } JNIEXPORT jint JNICALL Java_qdbm_Depot_dpfatalerror(JNIEnv *env, jclass myclass, jint index) { return dpfatalerror(dptable[index]); } JNIEXPORT jint JNICALL Java_qdbm_Depot_dpinode(JNIEnv *env, jclass myclass, jint index){ return dpinode(dptable[index]); } JNIEXPORT jlong JNICALL Java_qdbm_Depot_dpmtime(JNIEnv *env, jclass myclass, jint index){ return dpmtime(dptable[index]); } JNIEXPORT jint JNICALL Java_qdbm_Depot_dpremove(JNIEnv *env, jclass myclass, jstring name) { const char *tname; jboolean ic; int rv; tname = (*env)->GetStringUTFChars(env, name, &ic); rv = dpremove(tname); if(ic == JNI_TRUE) (*env)->ReleaseStringUTFChars(env, name, tname); return rv; } JNIEXPORT jbyteArray JNICALL Java_qdbm_Depot_dpsnaffle(JNIEnv *env, jclass myclass, jstring name, jbyteArray key, jint ksiz) { jbyte *kbuf; jboolean icn, ick; const char *tname; char *val; int vsiz; jbyteArray vbuf; tname = (*env)->GetStringUTFChars(env, name, &icn); kbuf = (*env)->GetByteArrayElements(env, key, &ick); val = dpsnaffle(tname, (char *)kbuf, ksiz, &vsiz); if(ick == JNI_TRUE) (*env)->ReleaseByteArrayElements(env, key, kbuf, JNI_ABORT); if(icn == JNI_TRUE) (*env)->ReleaseStringUTFChars(env, name, tname); if(val){ vbuf = (*env)->NewByteArray(env, vsiz); (*env)->SetByteArrayRegion(env, vbuf, 0, vsiz, (jbyte *)val); free(val); } else { vbuf = NULL; } return vbuf; } /************************************************************************************************* * private objects *************************************************************************************************/ static int getnewindex(void){ int i; for(i = 0; i < MAXOPEN; i++){ if(dptable[i] == NULL) return i; } return -1; } static int checkdup(const char *name){ struct stat sbuf; int i, inode; if(stat(name, &sbuf) == -1) return 0; inode = sbuf.st_ino; for(i = 0; i < MAXOPEN; i++){ if(dptable[i] != NULL && dpinode(dptable[i]) == inode) return -1; } return 0; } static int getdpomode(jint omode){ int dpomode; dpomode = DP_OREADER; if(omode & qdbm_Depot_OWRITER){ dpomode = DP_OWRITER; if(omode & qdbm_Depot_OCREAT) dpomode |= DP_OCREAT; if(omode & qdbm_Depot_OTRUNC) dpomode |= DP_OTRUNC; } if(omode & qdbm_Depot_ONOLCK) dpomode |= DP_ONOLCK; if(omode & qdbm_Depot_OLCKNB) dpomode |= DP_OLCKNB; if(omode & qdbm_Depot_OSPARSE) dpomode |= DP_OSPARSE; return dpomode; } static int getdpdmode(jint dmode){ switch(dmode){ case qdbm_Depot_DOVER: return DP_DOVER; case qdbm_Depot_DKEEP: return DP_DKEEP; case qdbm_Depot_DCAT: return DP_DCAT; } return -1; } /* END OF FILE */ qdbm-1.8.78/java/ADBM.java0000644000175000017500000000553510355663555014060 0ustar mikiomikio/************************************************************************************************* * Abstraction for database managers compatible with DBM * Copyright (C) 2000-2006 Mikio Hirabayashi * This file is part of QDBM, Quick Database Manager. * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU * Lesser General Public License as published by the Free Software Foundation; either version * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * You should have received a copy of the GNU Lesser General Public License along with QDBM; if * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. *************************************************************************************************/ package qdbm; /** * Abstraction for database managers compatible with DBM. */ public interface ADBM { //---------------------------------------------------------------- // methods //---------------------------------------------------------------- /** * Close the database connection. * @throws DBMException if an error occurs. */ void close() throws DBMException; /** * Store a record. * @param key a byte array of a key. * @param val a byte array of a value. * @param replace whether the existing value is to be overwritten or not. * @throws DBMException if an error occurs or replace is cancelled. */ void store(byte[] key, byte[] val, boolean replace) throws DBMException; /** * Delete a record. * @param key a byte array of a key. * @throws DBMException if an error occurs or no record corresponds. */ void delete(byte[] key) throws DBMException; /** * Fetch a record. * @param key a byte array of a key. * @return a byte array of the value of the corresponding record. * @throws DBMException if an error occurs or no record corresponds. */ byte[] fetch(byte[] key) throws DBMException; /** * Get the first key. * @return a byte array of the key of the first record. * @throws DBMException if an error occurs or no record corresponds. */ byte[] firstkey() throws DBMException; /** * Get the next key. * @return a byte array of the key of the next record. * @throws DBMException if an error occurs or no record corresponds. */ byte[] nextkey() throws DBMException; /** * Check whether a fatal error occured or not. * @return true if the database has a fatal error, false if not. * @throws DBMException if an error occurs. */ boolean error() throws DBMException; } /* END OF FILE */ qdbm-1.8.78/java/jcuria.c0000644000175000017500000003065310441455465014125 0ustar mikiomikio/************************************************************************************************* * Implementation of Curia for Java * Copyright (C) 2000-2006 Mikio Hirabayashi * This file is part of QDBM, Quick Database Manager. * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU * Lesser General Public License as published by the Free Software Foundation; either version * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * You should have received a copy of the GNU Lesser General Public License along with QDBM; if * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. *************************************************************************************************/ #include "qdbm_Curia.h" #include #include #include #include #include #include #define MAXOPEN 1024 CURIA *crtable[MAXOPEN]; static int getnewindex(void); static int checkdup(const char *name); static int getcromode(jint omode); static int getcrdmode(jint dmode); /************************************************************************************************* * public objects *************************************************************************************************/ JNIEXPORT void JNICALL Java_qdbm_Curia_crinit(JNIEnv *env, jclass myclass) { int i; for(i = 0; i < MAXOPEN; i++){ crtable[i] = NULL; } } JNIEXPORT jstring JNICALL Java_qdbm_Curia_crversion(JNIEnv *env, jclass myclass) { return (*env)->NewStringUTF(env, dpversion); } JNIEXPORT jint JNICALL Java_qdbm_Curia_crecode(JNIEnv *env, jclass myclass) { switch(dpecode){ case DP_ENOERR: return qdbm_Curia_ENOERR; case DP_EFATAL: return qdbm_Curia_EFATAL; case DP_EMODE: return qdbm_Curia_EMODE; case DP_EBROKEN: return qdbm_Curia_EBROKEN; case DP_EKEEP: return qdbm_Curia_EKEEP; case DP_ENOITEM: return qdbm_Curia_ENOITEM; case DP_EALLOC: return qdbm_Curia_EALLOC; case DP_EMAP: return qdbm_Curia_EMAP; case DP_EOPEN: return qdbm_Curia_EOPEN; case DP_ECLOSE: return qdbm_Curia_ECLOSE; case DP_ETRUNC: return qdbm_Curia_ETRUNC; case DP_ESYNC: return qdbm_Curia_ESYNC; case DP_ESTAT: return qdbm_Curia_ESTAT; case DP_ESEEK: return qdbm_Curia_ESEEK; case DP_EREAD: return qdbm_Curia_EREAD; case DP_EWRITE: return qdbm_Curia_EWRITE; case DP_ELOCK: return qdbm_Curia_ELOCK; case DP_EUNLINK: return qdbm_Curia_EUNLINK; case DP_EMKDIR: return qdbm_Curia_EMKDIR; case DP_ERMDIR: return qdbm_Curia_ERMDIR; case DP_EMISC: return qdbm_Curia_EMISC; } return -1; } JNIEXPORT jstring JNICALL Java_qdbm_Curia_crerrmsg(JNIEnv *env, jclass myclass, jint ecode) { return (*env)->NewStringUTF(env, dperrmsg(ecode)); } JNIEXPORT jint JNICALL Java_qdbm_Curia_cropen(JNIEnv *env, jclass myclass, jstring name, jint omode, jint bnum, jint dnum) { CURIA *curia; const char *tname; jboolean ic; int index; if((index = getnewindex()) == -1) return -1; tname = (*env)->GetStringUTFChars(env, name, &ic); if(checkdup(tname) == -1){ if(ic == JNI_TRUE) (*env)->ReleaseStringUTFChars(env, name, tname); dpecode = DP_EMISC; return -1; } curia = cropen(tname, getcromode(omode), bnum, dnum); if(ic == JNI_TRUE) (*env)->ReleaseStringUTFChars(env, name, tname); if(!curia) return -1; crtable[index] = curia; return index; } JNIEXPORT jint JNICALL Java_qdbm_Curia_crclose(JNIEnv *env, jclass myclass, jint index) { CURIA *curia; curia = crtable[index]; crtable[index] = NULL; return crclose(curia); } JNIEXPORT jint JNICALL Java_qdbm_Curia_crput(JNIEnv *env, jclass myclass, jint index, jbyteArray key, jint ksiz, jbyteArray val, jint vsiz, jint dmode){ jbyte *kbuf, *vbuf; jboolean ick, icv; int rv; kbuf = (*env)->GetByteArrayElements(env, key, &ick); vbuf = (*env)->GetByteArrayElements(env, val, &icv); rv = crput(crtable[index], (char *)kbuf, ksiz, (char *)vbuf, vsiz, getcrdmode(dmode)); if(ick == JNI_TRUE) (*env)->ReleaseByteArrayElements(env, key, kbuf, JNI_ABORT); if(icv == JNI_TRUE) (*env)->ReleaseByteArrayElements(env, val, vbuf, JNI_ABORT); return rv; } JNIEXPORT jint JNICALL Java_qdbm_Curia_crout(JNIEnv *env, jclass myclass, jint index, jbyteArray key, jint ksiz) { jbyte *kbuf; jboolean ick; int rv; kbuf = (*env)->GetByteArrayElements(env, key, &ick); rv = crout(crtable[index], (char *)kbuf, ksiz); if(ick == JNI_TRUE) (*env)->ReleaseByteArrayElements(env, key, kbuf, JNI_ABORT); return rv; } JNIEXPORT jbyteArray JNICALL Java_qdbm_Curia_crget(JNIEnv *env, jclass myclass, jint index, jbyteArray key, jint ksiz, jint start, jint max) { jbyte *kbuf; jboolean ick; char *val; int vsiz; jbyteArray vbuf; kbuf = (*env)->GetByteArrayElements(env, key, &ick); val = crget(crtable[index], (char *)kbuf, ksiz, start, max, &vsiz); if(ick == JNI_TRUE) (*env)->ReleaseByteArrayElements(env, key, kbuf, JNI_ABORT); if(val){ vbuf = (*env)->NewByteArray(env, vsiz); (*env)->SetByteArrayRegion(env, vbuf, 0, vsiz, (jbyte *)val); free(val); } else { vbuf = NULL; } return vbuf; } JNIEXPORT jint JNICALL Java_qdbm_Curia_crvsiz(JNIEnv *env, jclass myclass, jint index, jbyteArray key, jint ksiz) { jbyte *kbuf; jboolean ick; int rv; kbuf = (*env)->GetByteArrayElements(env, key, &ick); rv = crvsiz(crtable[index], (char *)kbuf, ksiz); if(ick == JNI_TRUE) (*env)->ReleaseByteArrayElements(env, key, kbuf, JNI_ABORT); return rv; } JNIEXPORT jint JNICALL Java_qdbm_Curia_criterinit(JNIEnv *env, jclass myclass, jint index) { return criterinit(crtable[index]); } JNIEXPORT jbyteArray JNICALL Java_qdbm_Curia_criternext(JNIEnv *env, jclass myclass, jint index) { char *val; int vsiz; jbyteArray vbuf; val = criternext(crtable[index], &vsiz); if(val){ vbuf = (*env)->NewByteArray(env, vsiz); (*env)->SetByteArrayRegion(env, vbuf, 0, vsiz, (jbyte *)val); free(val); } else { vbuf = NULL; } return vbuf; } JNIEXPORT jint JNICALL Java_qdbm_Curia_crsetalign(JNIEnv *env, jclass myclass, jint index, jint align) { return crsetalign(crtable[index], align); } JNIEXPORT jint JNICALL Java_qdbm_Curia_crsetfbpsiz(JNIEnv *env, jclass myclass, jint index, jint size) { return crsetfbpsiz(crtable[index], size); } JNIEXPORT jint JNICALL Java_qdbm_Curia_crsync(JNIEnv *env, jclass myclass, jint index) { return crsync(crtable[index]); } JNIEXPORT jint JNICALL Java_qdbm_Curia_croptimize(JNIEnv *env, jclass myclass, jint index, jint bnum) { return croptimize(crtable[index], bnum); } JNIEXPORT jstring JNICALL Java_qdbm_Curia_crname(JNIEnv *env, jclass myclass, jint index) { char *name; jstring nbuf; name = crname(crtable[index]); if(name){ nbuf = (*env)->NewStringUTF(env, name); free(name); } else { nbuf = NULL; } return nbuf; } JNIEXPORT jdouble JNICALL Java_qdbm_Curia_crfsizd(JNIEnv *env, jclass myclass, jint index) { return crfsizd(crtable[index]); } JNIEXPORT jint JNICALL Java_qdbm_Curia_crbnum(JNIEnv *env, jclass myclass, jint index) { return crbnum(crtable[index]); } JNIEXPORT jint JNICALL Java_qdbm_Curia_crbusenum(JNIEnv *env, jclass myclass, jint index) { return crbusenum(crtable[index]); } JNIEXPORT jint JNICALL Java_qdbm_Curia_crrnum(JNIEnv *env, jclass myclass, jint index) { return crrnum(crtable[index]); } JNIEXPORT jint JNICALL Java_qdbm_Curia_crwritable(JNIEnv *env, jclass myclass, jint index) { return crwritable(crtable[index]); } JNIEXPORT jint JNICALL Java_qdbm_Curia_crfatalerror(JNIEnv *env, jclass myclass, jint index) { return crfatalerror(crtable[index]); } JNIEXPORT jint JNICALL Java_qdbm_Curia_crinode(JNIEnv *env, jclass myclass, jint index) { return crinode(crtable[index]); } JNIEXPORT jlong JNICALL Java_qdbm_Curia_crmtime(JNIEnv *env, jclass myclass, jint index) { return crmtime(crtable[index]); } JNIEXPORT jint JNICALL Java_qdbm_Curia_crputlob(JNIEnv *env, jclass myclass, jint index, jbyteArray key, jint ksiz, jbyteArray val, jint vsiz, jint dmode) { jbyte *kbuf, *vbuf; jboolean ick, icv; int rv; kbuf = (*env)->GetByteArrayElements(env, key, &ick); vbuf = (*env)->GetByteArrayElements(env, val, &icv); rv = crputlob(crtable[index], (char *)kbuf, ksiz, (char *)vbuf, vsiz, getcrdmode(dmode)); if(ick == JNI_TRUE) (*env)->ReleaseByteArrayElements(env, key, kbuf, JNI_ABORT); if(icv == JNI_TRUE) (*env)->ReleaseByteArrayElements(env, val, vbuf, JNI_ABORT); return rv; } JNIEXPORT jint JNICALL Java_qdbm_Curia_croutlob(JNIEnv *env, jclass myclass, jint index, jbyteArray key, jint ksiz) { jbyte *kbuf; jboolean ick; int rv; kbuf = (*env)->GetByteArrayElements(env, key, &ick); rv = croutlob(crtable[index], (char *)kbuf, ksiz); if(ick == JNI_TRUE) (*env)->ReleaseByteArrayElements(env, key, kbuf, JNI_ABORT); return rv; } JNIEXPORT jbyteArray JNICALL Java_qdbm_Curia_crgetlob(JNIEnv *env, jclass myclass, jint index, jbyteArray key, jint ksiz, jint start, jint max) { jbyte *kbuf; jboolean ick; char *val; int vsiz; jbyteArray vbuf; kbuf = (*env)->GetByteArrayElements(env, key, &ick); val = crgetlob(crtable[index], (char *)kbuf, ksiz, start, max, &vsiz); if(ick == JNI_TRUE) (*env)->ReleaseByteArrayElements(env, key, kbuf, JNI_ABORT); if(val){ vbuf = (*env)->NewByteArray(env, vsiz); (*env)->SetByteArrayRegion(env, vbuf, 0, vsiz, (jbyte *)val); free(val); } else { vbuf = NULL; } return vbuf; } JNIEXPORT jint JNICALL Java_qdbm_Curia_crvsizlob(JNIEnv *env, jclass myclass, jint index, jbyteArray key, jint ksiz) { jbyte *kbuf; jboolean ick; int rv; kbuf = (*env)->GetByteArrayElements(env, key, &ick); rv = crvsizlob(crtable[index], (char *)kbuf, ksiz); if(ick == JNI_TRUE) (*env)->ReleaseByteArrayElements(env, key, kbuf, JNI_ABORT); return rv; } JNIEXPORT jint JNICALL Java_qdbm_Curia_crrnumlob(JNIEnv *env, jclass myclass, jint index) { return crrnumlob(crtable[index]); } JNIEXPORT jint JNICALL Java_qdbm_Curia_crremove(JNIEnv *env, jclass myclass, jstring name) { const char *tname; jboolean ic; int rv; tname = (*env)->GetStringUTFChars(env, name, &ic); rv = crremove(tname); if(ic == JNI_TRUE) (*env)->ReleaseStringUTFChars(env, name, tname); return rv; } JNIEXPORT jbyteArray JNICALL Java_qdbm_Curia_crsnaffle(JNIEnv *env, jclass myclass, jstring name, jbyteArray key, jint ksiz) { jbyte *kbuf; jboolean icn, ick; const char *tname; char *val; int vsiz; jbyteArray vbuf; tname = (*env)->GetStringUTFChars(env, name, &icn); kbuf = (*env)->GetByteArrayElements(env, key, &ick); val = crsnaffle(tname, (char *)kbuf, ksiz, &vsiz); if(ick == JNI_TRUE) (*env)->ReleaseByteArrayElements(env, key, kbuf, JNI_ABORT); if(icn == JNI_TRUE) (*env)->ReleaseStringUTFChars(env, name, tname); if(val){ vbuf = (*env)->NewByteArray(env, vsiz); (*env)->SetByteArrayRegion(env, vbuf, 0, vsiz, (jbyte *)val); free(val); } else { vbuf = NULL; } return vbuf; } /************************************************************************************************* * private objects *************************************************************************************************/ static int getnewindex(void){ int i; for(i = 0; i < MAXOPEN; i++){ if(crtable[i] == NULL) return i; } return -1; } static int checkdup(const char *name){ struct stat sbuf; int i, inode; if(stat(name, &sbuf) == -1) return 0; inode = sbuf.st_ino; for(i = 0; i < MAXOPEN; i++){ if(crtable[i] != NULL && crinode(crtable[i]) == inode) return -1; } return 0; } static int getcromode(jint omode){ int cromode; cromode = CR_OREADER; if(omode & qdbm_Curia_OWRITER){ cromode = CR_OWRITER; if(omode & qdbm_Curia_OCREAT) cromode |= CR_OCREAT; if(omode & qdbm_Curia_OTRUNC) cromode |= CR_OTRUNC; } if(omode & qdbm_Curia_ONOLCK) cromode |= CR_ONOLCK; if(omode & qdbm_Curia_OLCKNB) cromode |= CR_OLCKNB; if(omode & qdbm_Curia_OSPARSE) cromode |= CR_OSPARSE; return cromode; } static int getcrdmode(jint dmode){ switch(dmode){ case qdbm_Curia_DOVER: return CR_DOVER; case qdbm_Curia_DKEEP: return CR_DKEEP; case qdbm_Curia_DCAT: return CR_DCAT; } return -1; } /* END OF FILE */ qdbm-1.8.78/java/jspex.html0000644000175000017500000003573311426311621014514 0ustar mikiomikio Specifications of QDBM for Java

Specifications of QDBM for Java

Copyright (C) 2000-2006 Mikio Hirabayashi
Last Update: Thu, 26 Oct 2006 15:00:20 +0900

Table of Contents

  1. Overview
  2. Installation
  3. Setting
  4. Examples
  5. Bugs

Overview

QDBM provides API for Java. This encapsulates the basic API, the extended API, and the advanced API of QDBM, and make them thread-safe. These APIs are implemented with the APIs for C called with Java Native Interface.

The basic API for Java realizes a hash database with a file. Constructors of the class `Depot' open a database file. The method `close' is used in order to close the database. Although the finalizer also try to close the database, do not rely on it. The method `put' is used in order to store a record. The method `out' is used in order to delete a record. The method `get' is used in order to retrieve a record. Besides, most operations like ones of the basic API for C are available. Each methods throws an instance of the class `DepotException' if an error occurs.

The extended API for Java realizes a hash database with a directory and multiple files. Constructors of the class `Curia' open a database directory. The method `close' is used in order to close the database. Although the finalizer also try to close the database, do not rely on it. The method `put' is used in order to store a record. The method `out' is used in order to delete a record. The method `get' is used in order to retrieve a record. Operations for managing large objects are also provided. Besides, most operations like ones of the extended API for C are available. Each methods throws an instance of the class `CuriaException' if an error occurs.

The advanced API for Java realizes a B+ tree database with a file. Constructors of the class `Villa' open a database file. The method `close' is used in order to close the database. Although the finalizer also try to close the database, do not rely on it. The method `put' is used in order to store a record. The method `out' is used in order to delete a record. The method `get' is used in order to retrieve a record. Besides, most operations like ones of the advanced API for C are available. Each methods throws an instance of the class `VillaException' if an error occurs.

`Depot', `Curia', and `Villa' implement the interface `ADBM' which is abstraction of database managers compatible with DBM of UNIX standard. Each methods throws an instance of the class `DBMException'. When you choose the one of four APIs, `Depot' is suggested if performance is weighted, `Curia' is suggested if scalability is weighted, `Villa' is suggested if ordering access is required, `ADBM' is suggested if elegance and maintenance are weighted. Besides, a database file is not compatible with each API.

Each class is packaged in `qdbm'. You can import the package in source files of application.

While APIs for C are thread-safe unless plural threads do not share a database handle, APIs for Java are thread-safe even if plural threads share a handle.

When `put' overwriting an existing record is cancelled or `get' retrieving a missing record, failure of the operation is noticed by exception. If you dislike such behavior, set the `silent' flag to be true. Then, failure of the operation is noticed by the return value.

For more information about the APIs, read documents in the sub directory `japidoc'.


Installation

Preparation

Make sure that JDK of 1.2 or later version is installed, the environment variable `JAVA_HOME' is set appropriately. And make sure that QDBM is installed under `/usr/local'.

Change the current working directory to the sub directory named `java'.

cd java

Usual Steps

Run the configuration script. If you use GCC for Java compilation, append the option `--with-gcj'.

./configure

Build programs.

make

Perform self-diagnostic test.

make check

Install programs. This operation must be carried out by the root user.

make install

When a series of work finishes, a Java archive `qdbm.jar' is installed under the `/usr/local/lib'. And, such native libraries as `libjqdbm.so' are installed under `/usr/local/lib'.

To uninstall them, execute the following command after `./configure'. This operation must be carried out by the root user.

make uninstall

For Windows

On Windows (Cygwin), you should follow the procedures below for installation.

Run the configuration script.

./configure

Build programs.

make win

Perform self-diagnostic test.

make check-win

Install programs. As well, perform `make uninstall-win' to uninstall them.

make install-win

On Windows, an import library `libjqdbm.dll.a' is created, and a dynamic linking library `jqdbm.dll' is created instead of such a shared libraries as `libjqdbm.so'. `jqdbm.dll' is installed into `/usr/local/bin'.

In order to build QDBM using MinGW on Cygwin, you should perform `make mingw' instead of `make win'. With the UNIX emulation layer of Cygwin, generated programs depend on `cygwin1.dll'. This problem is solved by linking them to the Win32 native DLL with MinGW.

For Mac OS X

On Mac OS X (Darwin), you should follow the procedures below for installation.

Run the configuration script.

./configure

Build programs.

make mac

Perform self-diagnostic test.

make check-mac

Install programs. As well, perform `make uninstall-mac' to uninstall them.

make install-mac

On Mac OS X, `libjqdbm.dylib', `libqdbm.jnilib' and so on are created instead of `libjqdbm.so' and so on.

For HP-UX

On HP-UX, you should follow the procedures below for installation.

Run the configuration script.

./configure

Build programs.

make hpux

Perform self-diagnostic test.

make check-hpux

Install programs. As well, perform `make uninstall-hpux' to uninstall them.

make install-hpux

On HP-UX, `libjqdbm.sl' is created instead of `libjqdbm.so' and so on.


Setting

To build and execute programs using QDBM, the following environment variable should be set.

Set the class path, which the environment variable `CLASSPATH' defines, to include the full path of `qdbm.jar'.

CLASSPATH=$CLASSPATH:/usr/local/lib/qdbm.jar
export CLASSPATH

Set the library path, which the environment variable `LD_LIBRARY_PATH' defines, to include `/usr/local/lib'. As well, this setting is not wanted on Windows, and Mac OS X uses the environment variable `DYLD_LIBRARY_PATH', and HP-UX uses the environment variable `SHLIB_PATH'.

LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib
export LD_LIBRARY_PATH

Examples

The following example stores and retrieves a phone number, using the name as the key.

import qdbm.*;

public class Sample {

  static final String NAME = "mikio";
  static final String NUMBER = "000-1234-5678";
  static final String DBNAME = "book";

  public static void main(String[] args){
    Depot depot = null;
    try {

      // open the database
      depot = new Depot(DBNAME, Depot.OWRITER | Depot.OCREAT, -1);

      // store the record
      depot.put(NAME.getBytes(), NUMBER.getBytes());

      // retrieve the record
      byte[] res = depot.get(NAME.getBytes());
      System.out.println("Name: " + NAME);
      System.out.println("Number: " + new String(res));

    } catch(DepotException e){
      e.printStackTrace();
    } finally {

      // close the database
      if(depot != null){
        try {
          depot.close();
        } catch(DepotException e){
          e.printStackTrace();
        }
      }

    }
  }

}

The following example is a transcription of the one above, using the interface `ADBM'.

import qdbm.*;

public class Sample {

  static final String NAME = "mikio";
  static final String NUMBER = "000-1234-5678";
  static final String DBNAME = "book";

  public static void main(String[] args){
    ADBM dbm = null;
    try {

      // open the database
      dbm = new Depot(DBNAME, Depot.OWRITER | Depot.OCREAT, -1);

      // store the record
      dbm.store(NAME.getBytes(), NUMBER.getBytes(), true);

      // retrieve the record
      byte[] res = dbm.fetch(NAME.getBytes());
      System.out.println("Name: " + NAME);
      System.out.println("Number: " + new String(res));

    } catch(DBMException e){
      e.printStackTrace();
    } finally {

      // close the database
      if(dbm != null){
        try {
          dbm.close();
        } catch(DBMException e){
          e.printStackTrace();
        }
      }

    }
  }

}

The following example performs forward matching search for strings, using the class `Villa'.

import qdbm.*;

public class Sample {

  static final String DBNAME = "words";
  static final String PREFIX = "apple";

  public static void main(String[] args){
    Villa villa = null;
    try {

      // open the database
      villa = new Villa(DBNAME, Villa.OWRITER | Villa.OCREAT, Villa.CMPOBJ);

      // store records
      villa.putobj("applet", "little application", Villa.DDUP);
      villa.putobj("aurora", "polar wonderwork", Villa.DDUP);
      villa.putobj("apple", "delicious fruit", Villa.DDUP);
      villa.putobj("amigo", "good friend", Villa.DDUP);
      villa.putobj("apple", "big city", Villa.DDUP);

      try {

        // set the cursor at the top of candidates
        villa.curjumpobj(PREFIX, Villa.JFORWARD);

        // scan with the cursor
        for(;;){
          String key = (String)villa.curkeyobj();
          if(!key.startsWith(PREFIX)) break;
          String val = (String)villa.curvalobj();
          System.out.println(key + ": " + val);
          villa.curnext();
        }

      } catch(VillaException e){
        if(e.ecode != Villa.ENOITEM) throw e;
      }
    } catch(VillaException e){
      e.printStackTrace();
    } finally {

      // close the database
      if(villa != null){
        try {
          villa.close();
        } catch(VillaException e){
          e.printStackTrace();
        }
      }

    }
  }

}

For building a program using Java API of QDBM, set the environment variables and then perform `javac'. For example, the following command is executed to build `Sample.class' from `Sample.java'.

javac Sample.java

Bugs

QDBM has restrictions that two or more handles of the same database file should not be used by a process at the same time. So, when a database is used by two or more threads, open the database in the main thread and pass the handle to each thread.

Although methodology to store a serialized object is useful, object serialization is inefficient in time and space. So, if there is a method to get the byte array from an object, you should store the byte arrays. Besides, comparing keys in hash database is performed to serialized data even if they were objects. That is, if two objects are not according completely in serialized condition, even if the value of `equals' is true, they are not qualified as corresponding keys. This problem is not for B+ tree database, because the comparing function can be assigned appropriately.


qdbm-1.8.78/java/jutil.c0000644000175000017500000000513210355663556013777 0ustar mikiomikio/************************************************************************************************* * Implementation of Utilities of QDBM for Java * Copyright (C) 2000-2006 Mikio Hirabayashi * This file is part of QDBM, Quick Database Manager. * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU * Lesser General Public License as published by the Free Software Foundation; either version * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * You should have received a copy of the GNU Lesser General Public License along with QDBM; if * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. *************************************************************************************************/ #include "qdbm_Util.h" #include #include #include #define PATHBUFSIZ 2048 /************************************************************************************************* * public objects *************************************************************************************************/ JNIEXPORT jint JNICALL Java_qdbm_Util_system(JNIEnv *env, jclass myclass, jstring cmd) { const char *tmp; jboolean ic; int rv; tmp = (*env)->GetStringUTFChars(env, cmd, &ic); rv = system(tmp); if(ic == JNI_TRUE) (*env)->ReleaseStringUTFChars(env, cmd, tmp); return rv; } JNIEXPORT jint JNICALL Java_qdbm_Util_chdir(JNIEnv *env, jclass myclass, jstring path) { const char *tmp; jboolean ic; int rv; tmp = (*env)->GetStringUTFChars(env, path, &ic); rv = chdir(tmp); if(ic == JNI_TRUE) (*env)->ReleaseStringUTFChars(env, path, tmp); return rv; } JNIEXPORT jstring JNICALL Java_qdbm_Util_getcwd(JNIEnv *env, jclass myclass) { char path[PATHBUFSIZ]; if(!getcwd(path, PATHBUFSIZ)) return NULL; return (*env)->NewStringUTF(env, path); } JNIEXPORT jint JNICALL Java_qdbm_Util_getpid(JNIEnv *env, jclass myclass) { return getpid(); } JNIEXPORT jstring JNICALL Java_qdbm_Util_getenv(JNIEnv *env, jclass myclass, jstring name) { const char *tmp; char *val; jboolean ic; tmp = (*env)->GetStringUTFChars(env, name, &ic); val = getenv(tmp); if(ic == JNI_TRUE) (*env)->ReleaseStringUTFChars(env, name, tmp); if(!val) return 0; return (*env)->NewStringUTF(env, val); } /* END OF FILE */ qdbm-1.8.78/java/Makefile.in0000644000175000017500000001671510573423737014557 0ustar mikiomikio# Makefile for Java interface of QDBM #================================================================ # Setting variables #================================================================ # Generic settings SHELL = @SHELL@ srcdir = @srcdir@ VPATH = @srcdir@ # Packaging PACKAGE = qdbm LIBVER = @LIBVER@ LIBREV = @LIBREV@ # Targets MYCLASSES = ADBM.class DBMException.class Util.class \ Depot.class DepotException.class DepotTester.class \ Curia.class CuriaException.class CuriaTester.class \ Villa.class VillaCursor.class VillaException.class VillaTester.class MYJARS = qdbm.jar MYLIBOBJS = jdepot.o jcuria.o jvilla.o jutil.o MYLIBS = libjqdbm.so.$(LIBVER).$(LIBREV).0 libjqdbm.so.$(LIBVER) libjqdbm.so MYDOCS = jspex.html jspex-ja.html japidoc MYWINLIBS = libjqdbm.dll.a MYMACLIBS = libjqdbm.$(LIBVER).$(LIBREV).0.dylib libjqdbm.$(LIBVER).dylib \ libjqdbm.dylib libjqdbm.jnilib MYHPUXLIBS = libjqdbm.sl # Install destinations prefix = @prefix@ exec_prefix = @exec_prefix@ MYHEADDIR = @includedir@ MYLIBDIR = @libdir@ MYDATADIR = @datadir@/$(PACKAGE)/java DESTDIR = # Building binaries MYJAVAHOME = @MYJAVAHOME@ JVMPLATFORM = @JVMPLATFORM@ JAVAC = @JAVAC@ JAVACFLAGS = -d . JAR = @JAR@ JAVAH = @JAVAH@ JAVADOC = @JAVADOC@ JAVARUN = @JAVARUN@ CC = @CC@ CPPFLAGS = @CPPFLAGS@ -I$(srcdir) -I$(srcdir)/.. -I$(MYHEADDIR) \ -I$(HOME)/include -I/usr/local/include \ -I$(MYJAVAHOME)/include -I$(MYJAVAHOME)/include/$(JVMPLATFORM) -I$(MYJAVAHOME)/Headers \ @MYDEFS@ -D_XOPEN_SOURCE_EXTENDED=1 -D_GNU_SOURCE=1 -D__EXTENSIONS__=1 -D_HPUX_SOURCE=1 \ -D_POSIX_MAPPED_FILES=1 -D_POSIX_SYNCHRONIZED_IO=1 \ -DPIC=1 -D_THREAD_SAFE=1 -D_REENTRANT=1 -DNDEBUG CFLAGS = -Wall -fPIC -fsigned-char -O2 @MYOPTS@ LD = @LD@ LIBS = -lqdbm @LIBS@ LIBLDFLAGS = @LDFLAGS@ -L. -L$(srcdir)/.. -L$(MYLIBDIR) -L$(HOME)/lib -L/usr/local/lib $(LIBS) RUNENV = LD_LIBRARY_PATH=.:..:/lib:/usr/lib:$(MYLIBDIR):$(HOME)/lib:/usr/local/lib #================================================================ # Suffix rules #================================================================ .SUFFIXES : .SUFFIXES : .c .o .java .class .c.o : $(CC) $(CPPFLAGS) $(CFLAGS) -c $< .java.class : $(JAVAC) $(JAVACFLAGS) $(srcdir)/*.java for file in `ls qdbm` ;\ do \ ln -f -s qdbm/$$file . ;\ done #================================================================ # Actions #================================================================ targets : @TARGETS@ all : $(MYJARS) $(MYLIBS) @printf '\n' @printf '#================================================================\n' @printf '# Ready to install.\n' @printf '#================================================================\n' debug : make MYLIBS="$(MYLIBS)" JAVACFLAGS="-g $(JAVACFLAGS)" \ CPPFLAGS="$(CPPFLAGS) -UNDEBUG" CFLAGS="$(CFLAGS) -g" all devel : make MYLIBS="$(MYLIBS)" JAVACFLAGS="-g $(JAVACFLAGS)" \ CPPFLAGS="$(CPPFLAGS) -UNDEBUG" CFLAGS="$(CFLAGS) -g -pipe" all sync ; sync clean : rm -rf qdbm *.class $(MYLIBS) *.jar *.o *.a *.so \ *.exe *.dll.a *.dll *.dylib *.jnilib *.sl a.out casket *~ install : mkdir -p $(DESTDIR)$(MYLIBDIR) cp -Rf $(MYJARS) $(DESTDIR)$(MYLIBDIR) cp -Rf $(MYLIBS) $(DESTDIR)$(MYLIBDIR) mkdir -p $(DESTDIR)$(MYDATADIR) cp -Rf $(MYDOCS) $(DESTDIR)$(MYDATADIR) @printf '\n' @printf '#================================================================\n' @printf '# Thanks for using QDBM for Java.\n' @printf '#================================================================\n' uninstall : cd $(DESTDIR)$(MYLIBDIR) && rm -f $(MYJARS) cd $(DESTDIR)$(MYLIBDIR) && rm -f $(MYLIBS) rm -rf $(DESTDIR)$(MYDATADIR) dist : autoconf make doc make distclean distclean : clean rm -rf Makefile config.cache config.log config.status autom4te.cache head : Depot.class Curia.class Villa.class VillaCursor.class Util.class CLASSPATH=. $(JAVAH) -jni qdbm.Depot qdbm.Curia qdbm.Villa qdbm.VillaCursor qdbm.Util check : sync ; sync rm -rf casket $(RUNENV) CLASSPATH=qdbm.jar $(JAVARUN) qdbm.DepotTester casket @if [ -f casket ] ; then true ; else false ; fi rm -rf casket $(RUNENV) CLASSPATH=qdbm.jar $(JAVARUN) qdbm.CuriaTester casket @if [ -d casket ] ; then true ; else false ; fi rm -rf casket $(RUNENV) CLASSPATH=qdbm.jar $(JAVARUN) qdbm.VillaTester casket @if [ -f casket ] ; then true ; else false ; fi rm -rf casket @printf '\n' @printf '#================================================================\n' @printf '# Checking completed.\n' @printf '#================================================================\n' doc : make docclean mkdir -p japidoc $(JAVADOC) -locale en -windowtitle qdbm -overview joverview -tag note:a:"Note:" \ -d japidoc -nodeprecated -nohelp -quiet *.java dox : make docclean mkdir -p japidoc doxygen docclean : rm -rf japidoc win : make MYLIBS="$(MYWINLIBS)" CFLAGS="-Wall -fsigned-char -O0 -DNDEBUG" mingw : make CC="gcc -mno-cygwin" MYLIBS="$(MYWINLIBS)" \ CFLAGS="-Wall -fsigned-char -O0 -DNDEBUG" \ LIBLDFLAGS="-L. -L$(srcdir)/.. -L/usr/local/lib -lqdbm" check-win : make check install-win : make MYLIBS="$(MYWINLIBS)" install cp -Rf jqdbm.dll $(DESTDIR)$(MYBINDIR) uninstall-win : make MYLIBS="$(MYWINLIBS)" uninstall rm -f $(DESTDIR)$(MYBINDIR)/jqdbm.dll mac : make MYLIBS="$(MYMACLIBS)" CFLAGS="-Wall -fsigned-char -fno-common -O2 -DNDEBUG" check-mac : make RUNENV="DYLD_LIBRARY_PATH=.:..:/usr/local/lib" check install-mac : make MYLIBS="$(MYMACLIBS)" install uninstall-mac : make MYLIBS="$(MYMACLIBS)" uninstall hpux : make MYLIBS="$(MYHPUXLIBS)" check-hpux : make RUNENV="SHLIB_PATH=.:..:/usr/local/lib" check install-hpux : make MYLIBS="$(MYHPUXLIBS)" install uninstall-hpux : make MYLIBS="$(MYHPUXLIBS)" uninstall .PHONY : all clean install check #================================================================ # Building binaries #================================================================ qdbm.jar : $(MYCLASSES) $(JAR) cvf $@ qdbm/*.class libjqdbm.so.$(LIBVER).$(LIBREV).0 : $(MYLIBOBJS) if $(CC) --print-prog-name=ld | egrep -i '(solaris|/ccs/|/ucb/)' > /dev/null ; \ then \ $(CC) -shared -Wl,-G,-h,libjqdbm.so.$(LIBVER) -o $@ $(MYLIBOBJS) $(LIBLDFLAGS) ; \ else \ $(CC) -shared -Wl,-soname,libjqdbm.so.$(LIBVER) -o $@ $(MYLIBOBJS) $(LIBLDFLAGS) ; \ fi libjqdbm.so.$(LIBVER) : libjqdbm.so.$(LIBVER).$(LIBREV).0 ln -f -s libjqdbm.so.$(LIBVER).$(LIBREV).0 $@ libjqdbm.so : libjqdbm.so.$(LIBVER).$(LIBREV).0 ln -f -s libjqdbm.so.$(LIBVER).$(LIBREV).0 $@ libjqdbm.dll.a : jqdbm.dll jqdbm.dll : $(MYLIBOBJS) $(CC) -shared -o $@ \ -Wl,--out-implib=lib$@.a \ -Wl,--export-all-symbols \ -Wl,--enable-auto-import \ -Wl,--add-stdcall-alias \ -Wl,--whole-archive \ -Wl,--no-whole-archive $(MYLIBOBJS) $(LIBLDFLAGS) libjqdbm.$(LIBVER).$(LIBREV).0.dylib : $(MYLIBOBJS) $(CC) -dynamiclib -o $@ \ -install_name $(MYLIBDIR)/libjqdbm.$(LIBVER).dylib \ -current_version $(LIBVER).$(LIBREV).0 \ -compatibility_version $(LIBVER) \ $(MYLIBOBJS) $(LIBLDFLAGS) libjqdbm.$(LIBVER).dylib : libjqdbm.$(LIBVER).$(LIBREV).0.dylib ln -f -s libjqdbm.$(LIBVER).$(LIBREV).0.dylib $@ libjqdbm.dylib : libjqdbm.$(LIBVER).$(LIBREV).0.dylib ln -f -s libjqdbm.$(LIBVER).$(LIBREV).0.dylib $@ libjqdbm.jnilib : libjqdbm.$(LIBVER).$(LIBREV).0.dylib ln -f -s libjqdbm.$(LIBVER).$(LIBREV).0.dylib $@ libjqdbm.sl : $(MYLIBOBJS) $(CC) -shared -Wl,-b -o $@ $(MYLIBOBJS) $(LIBLDFLAGS) jdepot.o : qdbm_Depot.h jcuria.o : qdbm_Curia.h jvilla.o : qdbm_Villa.h qdbm_VillaCursor.h jutil.o : qdbm_Util.h # END OF FILE qdbm-1.8.78/java/qdbm_Util.h0000644000175000017500000000220710355663556014575 0ustar mikiomikio/* DO NOT EDIT THIS FILE - it is machine generated */ #include /* Header for class qdbm_Util */ #ifndef _Included_qdbm_Util #define _Included_qdbm_Util #ifdef __cplusplus extern "C" { #endif #undef qdbm_Util_LONGSIZE #define qdbm_Util_LONGSIZE 8L #undef qdbm_Util_IOBUFSIZ #define qdbm_Util_IOBUFSIZ 8192L /* * Class: qdbm_Util * Method: system * Signature: (Ljava/lang/String;)I */ JNIEXPORT jint JNICALL Java_qdbm_Util_system (JNIEnv *, jclass, jstring); /* * Class: qdbm_Util * Method: chdir * Signature: (Ljava/lang/String;)I */ JNIEXPORT jint JNICALL Java_qdbm_Util_chdir (JNIEnv *, jclass, jstring); /* * Class: qdbm_Util * Method: getcwd * Signature: ()Ljava/lang/String; */ JNIEXPORT jstring JNICALL Java_qdbm_Util_getcwd (JNIEnv *, jclass); /* * Class: qdbm_Util * Method: getpid * Signature: ()I */ JNIEXPORT jint JNICALL Java_qdbm_Util_getpid (JNIEnv *, jclass); /* * Class: qdbm_Util * Method: getenv * Signature: (Ljava/lang/String;)Ljava/lang/String; */ JNIEXPORT jstring JNICALL Java_qdbm_Util_getenv (JNIEnv *, jclass, jstring); #ifdef __cplusplus } #endif #endif qdbm-1.8.78/java/qdbm_Villa.h0000644000175000017500000002036710362224262014717 0ustar mikiomikio/* DO NOT EDIT THIS FILE - it is machine generated */ #include /* Header for class qdbm_Villa */ #ifndef _Included_qdbm_Villa #define _Included_qdbm_Villa #ifdef __cplusplus extern "C" { #endif #undef qdbm_Villa_ENOERR #define qdbm_Villa_ENOERR 0L #undef qdbm_Villa_EFATAL #define qdbm_Villa_EFATAL 1L #undef qdbm_Villa_EMODE #define qdbm_Villa_EMODE 2L #undef qdbm_Villa_EBROKEN #define qdbm_Villa_EBROKEN 3L #undef qdbm_Villa_EKEEP #define qdbm_Villa_EKEEP 4L #undef qdbm_Villa_ENOITEM #define qdbm_Villa_ENOITEM 5L #undef qdbm_Villa_EALLOC #define qdbm_Villa_EALLOC 6L #undef qdbm_Villa_EMAP #define qdbm_Villa_EMAP 7L #undef qdbm_Villa_EOPEN #define qdbm_Villa_EOPEN 8L #undef qdbm_Villa_ECLOSE #define qdbm_Villa_ECLOSE 9L #undef qdbm_Villa_ETRUNC #define qdbm_Villa_ETRUNC 10L #undef qdbm_Villa_ESYNC #define qdbm_Villa_ESYNC 11L #undef qdbm_Villa_ESTAT #define qdbm_Villa_ESTAT 12L #undef qdbm_Villa_ESEEK #define qdbm_Villa_ESEEK 13L #undef qdbm_Villa_EREAD #define qdbm_Villa_EREAD 14L #undef qdbm_Villa_EWRITE #define qdbm_Villa_EWRITE 15L #undef qdbm_Villa_ELOCK #define qdbm_Villa_ELOCK 16L #undef qdbm_Villa_EUNLINK #define qdbm_Villa_EUNLINK 17L #undef qdbm_Villa_EMKDIR #define qdbm_Villa_EMKDIR 18L #undef qdbm_Villa_ERMDIR #define qdbm_Villa_ERMDIR 19L #undef qdbm_Villa_EMISC #define qdbm_Villa_EMISC 20L #undef qdbm_Villa_OREADER #define qdbm_Villa_OREADER 1L #undef qdbm_Villa_OWRITER #define qdbm_Villa_OWRITER 2L #undef qdbm_Villa_OCREAT #define qdbm_Villa_OCREAT 4L #undef qdbm_Villa_OTRUNC #define qdbm_Villa_OTRUNC 8L #undef qdbm_Villa_ONOLCK #define qdbm_Villa_ONOLCK 16L #undef qdbm_Villa_OLCKNB #define qdbm_Villa_OLCKNB 32L #undef qdbm_Villa_OZCOMP #define qdbm_Villa_OZCOMP 64L #undef qdbm_Villa_OYCOMP #define qdbm_Villa_OYCOMP 128L #undef qdbm_Villa_OXCOMP #define qdbm_Villa_OXCOMP 256L #undef qdbm_Villa_CMPLEX #define qdbm_Villa_CMPLEX 0L #undef qdbm_Villa_CMPNUM #define qdbm_Villa_CMPNUM 1L #undef qdbm_Villa_CMPDEC #define qdbm_Villa_CMPDEC 2L #undef qdbm_Villa_CMPOBJ #define qdbm_Villa_CMPOBJ 3L #undef qdbm_Villa_DOVER #define qdbm_Villa_DOVER 0L #undef qdbm_Villa_DKEEP #define qdbm_Villa_DKEEP 1L #undef qdbm_Villa_DCAT #define qdbm_Villa_DCAT 2L #undef qdbm_Villa_DDUP #define qdbm_Villa_DDUP 3L #undef qdbm_Villa_DDUPR #define qdbm_Villa_DDUPR 4L #undef qdbm_Villa_JFORWARD #define qdbm_Villa_JFORWARD 0L #undef qdbm_Villa_JBACKWARD #define qdbm_Villa_JBACKWARD 1L #undef qdbm_Villa_CPCURRENT #define qdbm_Villa_CPCURRENT 0L #undef qdbm_Villa_CPBEFORE #define qdbm_Villa_CPBEFORE 1L #undef qdbm_Villa_CPAFTER #define qdbm_Villa_CPAFTER 2L /* Inaccessible static: class_00024qdbm_00024ADBM */ /* * Class: qdbm_Villa * Method: vlinit * Signature: ()V */ JNIEXPORT void JNICALL Java_qdbm_Villa_vlinit (JNIEnv *, jclass); /* * Class: qdbm_Villa * Method: vlversion * Signature: ()Ljava/lang/String; */ JNIEXPORT jstring JNICALL Java_qdbm_Villa_vlversion (JNIEnv *, jclass); /* * Class: qdbm_Villa * Method: vlecode * Signature: ()I */ JNIEXPORT jint JNICALL Java_qdbm_Villa_vlecode (JNIEnv *, jclass); /* * Class: qdbm_Villa * Method: vlerrmsg * Signature: (I)Ljava/lang/String; */ JNIEXPORT jstring JNICALL Java_qdbm_Villa_vlerrmsg (JNIEnv *, jclass, jint); /* * Class: qdbm_Villa * Method: vlopen * Signature: (Ljava/lang/String;II)I */ JNIEXPORT jint JNICALL Java_qdbm_Villa_vlopen (JNIEnv *, jclass, jstring, jint, jint); /* * Class: qdbm_Villa * Method: vlclose * Signature: (I)I */ JNIEXPORT jint JNICALL Java_qdbm_Villa_vlclose (JNIEnv *, jclass, jint); /* * Class: qdbm_Villa * Method: vlput * Signature: (I[BI[BII)I */ JNIEXPORT jint JNICALL Java_qdbm_Villa_vlput (JNIEnv *, jclass, jint, jbyteArray, jint, jbyteArray, jint, jint); /* * Class: qdbm_Villa * Method: vlout * Signature: (I[BI)I */ JNIEXPORT jint JNICALL Java_qdbm_Villa_vlout (JNIEnv *, jclass, jint, jbyteArray, jint); /* * Class: qdbm_Villa * Method: vlget * Signature: (I[BI)[B */ JNIEXPORT jbyteArray JNICALL Java_qdbm_Villa_vlget (JNIEnv *, jclass, jint, jbyteArray, jint); /* * Class: qdbm_Villa * Method: vlvsiz * Signature: (I[BI)I */ JNIEXPORT jint JNICALL Java_qdbm_Villa_vlvsiz (JNIEnv *, jclass, jint, jbyteArray, jint); /* * Class: qdbm_Villa * Method: vlvnum * Signature: (I[BI)I */ JNIEXPORT jint JNICALL Java_qdbm_Villa_vlvnum (JNIEnv *, jclass, jint, jbyteArray, jint); /* * Class: qdbm_Villa * Method: vlcurfirst * Signature: (I)I */ JNIEXPORT jint JNICALL Java_qdbm_Villa_vlcurfirst (JNIEnv *, jclass, jint); /* * Class: qdbm_Villa * Method: vlcurlast * Signature: (I)I */ JNIEXPORT jint JNICALL Java_qdbm_Villa_vlcurlast (JNIEnv *, jclass, jint); /* * Class: qdbm_Villa * Method: vlcurprev * Signature: (I)I */ JNIEXPORT jint JNICALL Java_qdbm_Villa_vlcurprev (JNIEnv *, jclass, jint); /* * Class: qdbm_Villa * Method: vlcurnext * Signature: (I)I */ JNIEXPORT jint JNICALL Java_qdbm_Villa_vlcurnext (JNIEnv *, jclass, jint); /* * Class: qdbm_Villa * Method: vlcurjump * Signature: (I[BII)I */ JNIEXPORT jint JNICALL Java_qdbm_Villa_vlcurjump (JNIEnv *, jclass, jint, jbyteArray, jint, jint); /* * Class: qdbm_Villa * Method: vlcurkey * Signature: (I)[B */ JNIEXPORT jbyteArray JNICALL Java_qdbm_Villa_vlcurkey (JNIEnv *, jclass, jint); /* * Class: qdbm_Villa * Method: vlcurval * Signature: (I)[B */ JNIEXPORT jbyteArray JNICALL Java_qdbm_Villa_vlcurval (JNIEnv *, jclass, jint); /* * Class: qdbm_Villa * Method: vlcurput * Signature: (I[BII)I */ JNIEXPORT jint JNICALL Java_qdbm_Villa_vlcurput (JNIEnv *, jclass, jint, jbyteArray, jint, jint); /* * Class: qdbm_Villa * Method: vlcurout * Signature: (I)I */ JNIEXPORT jint JNICALL Java_qdbm_Villa_vlcurout (JNIEnv *, jclass, jint); /* * Class: qdbm_Villa * Method: vlsettuning * Signature: (IIIII)V */ JNIEXPORT void JNICALL Java_qdbm_Villa_vlsettuning (JNIEnv *, jclass, jint, jint, jint, jint, jint); /* * Class: qdbm_Villa * Method: vlsync * Signature: (I)I */ JNIEXPORT jint JNICALL Java_qdbm_Villa_vlsync (JNIEnv *, jclass, jint); /* * Class: qdbm_Villa * Method: vloptimize * Signature: (I)I */ JNIEXPORT jint JNICALL Java_qdbm_Villa_vloptimize (JNIEnv *, jclass, jint); /* * Class: qdbm_Villa * Method: vlname * Signature: (I)Ljava/lang/String; */ JNIEXPORT jstring JNICALL Java_qdbm_Villa_vlname (JNIEnv *, jclass, jint); /* * Class: qdbm_Villa * Method: vlfsiz * Signature: (I)I */ JNIEXPORT jint JNICALL Java_qdbm_Villa_vlfsiz (JNIEnv *, jclass, jint); /* * Class: qdbm_Villa * Method: vllnum * Signature: (I)I */ JNIEXPORT jint JNICALL Java_qdbm_Villa_vllnum (JNIEnv *, jclass, jint); /* * Class: qdbm_Villa * Method: vlnnum * Signature: (I)I */ JNIEXPORT jint JNICALL Java_qdbm_Villa_vlnnum (JNIEnv *, jclass, jint); /* * Class: qdbm_Villa * Method: vlrnum * Signature: (I)I */ JNIEXPORT jint JNICALL Java_qdbm_Villa_vlrnum (JNIEnv *, jclass, jint); /* * Class: qdbm_Villa * Method: vlwritable * Signature: (I)I */ JNIEXPORT jint JNICALL Java_qdbm_Villa_vlwritable (JNIEnv *, jclass, jint); /* * Class: qdbm_Villa * Method: vlfatalerror * Signature: (I)I */ JNIEXPORT jint JNICALL Java_qdbm_Villa_vlfatalerror (JNIEnv *, jclass, jint); /* * Class: qdbm_Villa * Method: vlinode * Signature: (I)I */ JNIEXPORT jint JNICALL Java_qdbm_Villa_vlinode (JNIEnv *, jclass, jint); /* * Class: qdbm_Villa * Method: vlmtime * Signature: (I)J */ JNIEXPORT jlong JNICALL Java_qdbm_Villa_vlmtime (JNIEnv *, jclass, jint); /* * Class: qdbm_Villa * Method: vltranbegin * Signature: (I)I */ JNIEXPORT jint JNICALL Java_qdbm_Villa_vltranbegin (JNIEnv *, jclass, jint); /* * Class: qdbm_Villa * Method: vltrancommit * Signature: (I)I */ JNIEXPORT jint JNICALL Java_qdbm_Villa_vltrancommit (JNIEnv *, jclass, jint); /* * Class: qdbm_Villa * Method: vltranabort * Signature: (I)I */ JNIEXPORT jint JNICALL Java_qdbm_Villa_vltranabort (JNIEnv *, jclass, jint); /* * Class: qdbm_Villa * Method: vlremove * Signature: (Ljava/lang/String;)I */ JNIEXPORT jint JNICALL Java_qdbm_Villa_vlremove (JNIEnv *, jclass, jstring); #ifdef __cplusplus } #endif #endif qdbm-1.8.78/java/CuriaException.java0000644000175000017500000000347310355663555016276 0ustar mikiomikio/************************************************************************************************* * Exception container of Curia * Copyright (C) 2000-2006 Mikio Hirabayashi * This file is part of QDBM, Quick Database Manager. * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU * Lesser General Public License as published by the Free Software Foundation; either version * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * You should have received a copy of the GNU Lesser General Public License along with QDBM; if * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. *************************************************************************************************/ package qdbm; /** * Exception container of Curia. */ public class CuriaException extends DBMException { //---------------------------------------------------------------- // instance fields //---------------------------------------------------------------- /** error code */ public final int ecode; //---------------------------------------------------------------- // public or protected methods //---------------------------------------------------------------- /** * Set the error code with `Curia.EMISC'. */ public CuriaException(){ this(Curia.EMISC); } /** * Set the error code. * @param ecode an error code. */ public CuriaException(int ecode){ super(Curia.errmsg(ecode)); this.ecode = ecode; } } /* END OF FILE */ qdbm-1.8.78/java/qdbm_VillaCursor.h0000644000175000017500000000401210441467234016110 0ustar mikiomikio/* DO NOT EDIT THIS FILE - it is machine generated */ #include /* Header for class qdbm_VillaCursor */ #ifndef _Included_qdbm_VillaCursor #define _Included_qdbm_VillaCursor #ifdef __cplusplus extern "C" { #endif /* Inaccessible static: class_00024qdbm_00024ADBM */ /* * Class: qdbm_VillaCursor * Method: vlmulcurecode * Signature: ()I */ JNIEXPORT jint JNICALL Java_qdbm_VillaCursor_vlmulcurecode (JNIEnv *, jclass); /* * Class: qdbm_VillaCursor * Method: vlmulcurnew * Signature: (I)I */ JNIEXPORT jint JNICALL Java_qdbm_VillaCursor_vlmulcurnew (JNIEnv *, jobject, jint); /* * Class: qdbm_VillaCursor * Method: vlmulcurdelete * Signature: ()V */ JNIEXPORT void JNICALL Java_qdbm_VillaCursor_vlmulcurdelete (JNIEnv *, jobject); /* * Class: qdbm_VillaCursor * Method: vlmulcurfirst * Signature: (I)I */ JNIEXPORT jint JNICALL Java_qdbm_VillaCursor_vlmulcurfirst (JNIEnv *, jobject, jint); /* * Class: qdbm_VillaCursor * Method: vlmulcurlast * Signature: (I)I */ JNIEXPORT jint JNICALL Java_qdbm_VillaCursor_vlmulcurlast (JNIEnv *, jobject, jint); /* * Class: qdbm_VillaCursor * Method: vlmulcurprev * Signature: (I)I */ JNIEXPORT jint JNICALL Java_qdbm_VillaCursor_vlmulcurprev (JNIEnv *, jobject, jint); /* * Class: qdbm_VillaCursor * Method: vlmulcurnext * Signature: (I)I */ JNIEXPORT jint JNICALL Java_qdbm_VillaCursor_vlmulcurnext (JNIEnv *, jobject, jint); /* * Class: qdbm_VillaCursor * Method: vlmulcurjump * Signature: (I[BII)I */ JNIEXPORT jint JNICALL Java_qdbm_VillaCursor_vlmulcurjump (JNIEnv *, jobject, jint, jbyteArray, jint, jint); /* * Class: qdbm_VillaCursor * Method: vlmulcurkey * Signature: (I)[B */ JNIEXPORT jbyteArray JNICALL Java_qdbm_VillaCursor_vlmulcurkey (JNIEnv *, jobject, jint); /* * Class: qdbm_VillaCursor * Method: vlmulcurval * Signature: (I)[B */ JNIEXPORT jbyteArray JNICALL Java_qdbm_VillaCursor_vlmulcurval (JNIEnv *, jobject, jint); #ifdef __cplusplus } #endif #endif qdbm-1.8.78/java/jvilla.c0000644000175000017500000004560210441502657014125 0ustar mikiomikio/************************************************************************************************* * Implementation of Villa for Java * Copyright (C) 2000-2006 Mikio Hirabayashi * This file is part of QDBM, Quick Database Manager. * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU * Lesser General Public License as published by the Free Software Foundation; either version * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * You should have received a copy of the GNU Lesser General Public License along with QDBM; if * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. *************************************************************************************************/ #include "qdbm_Villa.h" #include "qdbm_VillaCursor.h" #include #include #include #include #include #include #include #if SIZEOF_VOID_P == SIZEOF_INT #define PTRNUM jint #else #define PTRNUM jlong #endif #define MAXOPEN 1024 JNIEnv *vljnienv; jclass vlmyclass; VILLA *vltable[MAXOPEN]; static int getnewindex(void); static int checkdup(const char *name); static int getvlomode(jint omode); static VLCFUNC getvlcmp(jint cmode); static int getvldmode(jint dmode); static int getvljmode(jint jmode); static int getvlcpmode(jint cpmode); static int objcompare(const char *aptr, int asiz, const char *bptr, int bsiz); /************************************************************************************************* * public objects *************************************************************************************************/ JNIEXPORT void JNICALL Java_qdbm_Villa_vlinit(JNIEnv *env, jclass myclass) { int i; for(i = 0; i < MAXOPEN; i++){ vltable[i] = NULL; } } JNIEXPORT jstring JNICALL Java_qdbm_Villa_vlversion(JNIEnv *env, jclass myclass) { return (*env)->NewStringUTF(env, dpversion); } JNIEXPORT jint JNICALL Java_qdbm_Villa_vlecode(JNIEnv *env, jclass myclass) { switch(dpecode){ case DP_ENOERR: return qdbm_Villa_ENOERR; case DP_EFATAL: return qdbm_Villa_EFATAL; case DP_EMODE: return qdbm_Villa_EMODE; case DP_EBROKEN: return qdbm_Villa_EBROKEN; case DP_EKEEP: return qdbm_Villa_EKEEP; case DP_ENOITEM: return qdbm_Villa_ENOITEM; case DP_EALLOC: return qdbm_Villa_EALLOC; case DP_EMAP: return qdbm_Villa_EMAP; case DP_EOPEN: return qdbm_Villa_EOPEN; case DP_ECLOSE: return qdbm_Villa_ECLOSE; case DP_ETRUNC: return qdbm_Villa_ETRUNC; case DP_ESYNC: return qdbm_Villa_ESYNC; case DP_ESTAT: return qdbm_Villa_ESTAT; case DP_ESEEK: return qdbm_Villa_ESEEK; case DP_EREAD: return qdbm_Villa_EREAD; case DP_EWRITE: return qdbm_Villa_EWRITE; case DP_ELOCK: return qdbm_Villa_ELOCK; case DP_EUNLINK: return qdbm_Villa_EUNLINK; case DP_EMKDIR: return qdbm_Villa_EMKDIR; case DP_ERMDIR: return qdbm_Villa_ERMDIR; case DP_EMISC: return qdbm_Villa_EMISC; } return -1; } JNIEXPORT jstring JNICALL Java_qdbm_Villa_vlerrmsg(JNIEnv *env, jclass myclass, jint ecode) { return (*env)->NewStringUTF(env, dperrmsg(ecode)); } JNIEXPORT jint JNICALL Java_qdbm_Villa_vlopen(JNIEnv *env, jclass myclass, jstring name, jint omode, jint cmode) { VILLA *villa; const char *tname; jboolean ic; int index; VLCFUNC cmp; vljnienv = env; vlmyclass = myclass; if((index = getnewindex()) == -1) return -1; tname = (*env)->GetStringUTFChars(env, name, &ic); cmp = NULL; if(checkdup(tname) == -1 || !(cmp = getvlcmp(cmode))){ if(ic == JNI_TRUE) (*env)->ReleaseStringUTFChars(env, name, tname); dpecode = DP_EMISC; return -1; } villa = vlopen(tname, getvlomode(omode), cmp); if(ic == JNI_TRUE) (*env)->ReleaseStringUTFChars(env, name, tname); if(!villa) return -1; vltable[index] = villa; return index; } JNIEXPORT jint JNICALL Java_qdbm_Villa_vlclose(JNIEnv *env, jclass myclass, jint index) { VILLA *villa; vljnienv = env; vlmyclass = myclass; villa = vltable[index]; vltable[index] = NULL; return vlclose(villa); } JNIEXPORT jint JNICALL Java_qdbm_Villa_vlput(JNIEnv *env, jclass myclass, jint index, jbyteArray key, jint ksiz, jbyteArray val, jint vsiz, jint dmode) { jbyte *kbuf, *vbuf; jboolean ick, icv; int rv; vljnienv = env; vlmyclass = myclass; kbuf = (*env)->GetByteArrayElements(env, key, &ick); vbuf = (*env)->GetByteArrayElements(env, val, &icv); rv = vlput(vltable[index], (char *)kbuf, ksiz, (char *)vbuf, vsiz, getvldmode(dmode)); if(ick == JNI_TRUE) (*env)->ReleaseByteArrayElements(env, key, kbuf, JNI_ABORT); if(icv == JNI_TRUE) (*env)->ReleaseByteArrayElements(env, val, vbuf, JNI_ABORT); return rv; } JNIEXPORT jint JNICALL Java_qdbm_Villa_vlout(JNIEnv *env, jclass myclass, jint index, jbyteArray key, jint ksiz) { jbyte *kbuf; jboolean ick; int rv; vljnienv = env; vlmyclass = myclass; kbuf = (*env)->GetByteArrayElements(env, key, &ick); rv = vlout(vltable[index], (char *)kbuf, ksiz); if(ick == JNI_TRUE) (*env)->ReleaseByteArrayElements(env, key, kbuf, JNI_ABORT); return rv; } JNIEXPORT jbyteArray JNICALL Java_qdbm_Villa_vlget(JNIEnv *env, jclass myclass, jint index, jbyteArray key, jint ksiz) { jbyte *kbuf; jboolean ick; const char *val; int vsiz; jbyteArray vbuf; vljnienv = env; vlmyclass = myclass; kbuf = (*env)->GetByteArrayElements(env, key, &ick); val = vlgetcache(vltable[index], (char *)kbuf, ksiz, &vsiz); if(ick == JNI_TRUE) (*env)->ReleaseByteArrayElements(env, key, kbuf, JNI_ABORT); if(val){ vbuf = (*env)->NewByteArray(env, vsiz); (*env)->SetByteArrayRegion(env, vbuf, 0, vsiz, (jbyte *)val); } else { vbuf = NULL; } return vbuf; } JNIEXPORT jint JNICALL Java_qdbm_Villa_vlvsiz(JNIEnv *env, jclass myclass, jint index, jbyteArray key, jint ksiz) { jbyte *kbuf; jboolean ick; int rv; vljnienv = env; vlmyclass = myclass; kbuf = (*env)->GetByteArrayElements(env, key, &ick); rv = vlvsiz(vltable[index], (char *)kbuf, ksiz); if(ick == JNI_TRUE) (*env)->ReleaseByteArrayElements(env, key, kbuf, JNI_ABORT); return rv; } JNIEXPORT jint JNICALL Java_qdbm_Villa_vlvnum(JNIEnv *env, jclass myclass, jint index, jbyteArray key, jint ksiz) { jbyte *kbuf; jboolean ick; int rv; vljnienv = env; vlmyclass = myclass; kbuf = (*env)->GetByteArrayElements(env, key, &ick); rv = vlvnum(vltable[index], (char *)kbuf, ksiz); if(ick == JNI_TRUE) (*env)->ReleaseByteArrayElements(env, key, kbuf, JNI_ABORT); return rv; } JNIEXPORT jint JNICALL Java_qdbm_Villa_vlcurfirst(JNIEnv *env, jclass myclass, jint index) { vljnienv = env; vlmyclass = myclass; return vlcurfirst(vltable[index]); } JNIEXPORT jint JNICALL Java_qdbm_Villa_vlcurlast(JNIEnv *env, jclass myclass, jint index) { vljnienv = env; vlmyclass = myclass; return vlcurlast(vltable[index]); } JNIEXPORT jint JNICALL Java_qdbm_Villa_vlcurprev(JNIEnv *env, jclass myclass, jint index) { vljnienv = env; vlmyclass = myclass; return vlcurprev(vltable[index]); } JNIEXPORT jint JNICALL Java_qdbm_Villa_vlcurnext(JNIEnv *env, jclass myclass, jint index) { vljnienv = env; vlmyclass = myclass; return vlcurnext(vltable[index]); } JNIEXPORT jint JNICALL Java_qdbm_Villa_vlcurjump(JNIEnv *env, jclass myclass, jint index, jbyteArray key, jint ksiz, jint jmode) { jbyte *kbuf; jboolean ick; int rv; vljnienv = env; vlmyclass = myclass; kbuf = (*env)->GetByteArrayElements(env, key, &ick); rv = vlcurjump(vltable[index], (char *)kbuf, ksiz, getvljmode(jmode)); if(ick == JNI_TRUE) (*env)->ReleaseByteArrayElements(env, key, kbuf, JNI_ABORT); return rv; } JNIEXPORT jbyteArray JNICALL Java_qdbm_Villa_vlcurkey(JNIEnv *env, jclass myclass, jint index) { const char *key; int ksiz; jbyteArray kbuf; vljnienv = env; vlmyclass = myclass; key = vlcurkeycache(vltable[index], &ksiz); if(key){ kbuf = (*env)->NewByteArray(env, ksiz); (*env)->SetByteArrayRegion(env, kbuf, 0, ksiz, (jbyte *)key); } else { kbuf = NULL; } return kbuf; } JNIEXPORT jbyteArray JNICALL Java_qdbm_Villa_vlcurval(JNIEnv *env, jclass myclass, jint index) { const char *val; int vsiz; jbyteArray vbuf; vljnienv = env; vlmyclass = myclass; val = vlcurvalcache(vltable[index], &vsiz); if(val){ vbuf = (*env)->NewByteArray(env, vsiz); (*env)->SetByteArrayRegion(env, vbuf, 0, vsiz, (jbyte *)val); } else { vbuf = NULL; } return vbuf; } JNIEXPORT jint JNICALL Java_qdbm_Villa_vlcurput(JNIEnv *env, jclass myclass, jint index, jbyteArray val, jint vsiz, jint cpmode){ jbyte *vbuf; jboolean icv; int rv; vljnienv = env; vlmyclass = myclass; vbuf = (*env)->GetByteArrayElements(env, val, &icv); rv = vlcurput(vltable[index], (char *)vbuf, vsiz, getvlcpmode(cpmode)); if(icv == JNI_TRUE) (*env)->ReleaseByteArrayElements(env, val, vbuf, JNI_ABORT); return rv; } JNIEXPORT jint JNICALL Java_qdbm_Villa_vlcurout(JNIEnv *env, jclass myclass, jint index){ vljnienv = env; vlmyclass = myclass; return vlcurout(vltable[index]); } JNIEXPORT void JNICALL Java_qdbm_Villa_vlsettuning(JNIEnv *env, jclass myclass, jint index, jint lrecmax, jint nidxmax, jint lcnum, jint ncnum) { vljnienv = env; vlmyclass = myclass; vlsettuning(vltable[index], lrecmax, nidxmax, lcnum, ncnum); } JNIEXPORT jint JNICALL Java_qdbm_Villa_vlsync(JNIEnv *env, jclass myclass, jint index) { vljnienv = env; vlmyclass = myclass; return vlsync(vltable[index]); } JNIEXPORT jint JNICALL Java_qdbm_Villa_vloptimize(JNIEnv *env, jclass myclass, jint index) { vljnienv = env; vlmyclass = myclass; return vloptimize(vltable[index]); } JNIEXPORT jstring JNICALL Java_qdbm_Villa_vlname(JNIEnv *env, jclass myclass, jint index) { char *name; jstring nbuf; vljnienv = env; vlmyclass = myclass; name = vlname(vltable[index]); if(name){ nbuf = (*env)->NewStringUTF(env, name); free(name); } else { nbuf = NULL; } return nbuf; } JNIEXPORT jint JNICALL Java_qdbm_Villa_vlfsiz(JNIEnv *env, jclass myclass, jint index) { vljnienv = env; vlmyclass = myclass; return vlfsiz(vltable[index]); } JNIEXPORT jint JNICALL Java_qdbm_Villa_vllnum(JNIEnv *env, jclass myclass, jint index) { vljnienv = env; vlmyclass = myclass; return vllnum(vltable[index]); } JNIEXPORT jint JNICALL Java_qdbm_Villa_vlnnum(JNIEnv *env, jclass myclass, jint index) { vljnienv = env; vlmyclass = myclass; return vlnnum(vltable[index]); } JNIEXPORT jint JNICALL Java_qdbm_Villa_vlrnum(JNIEnv *env, jclass myclass, jint index) { vljnienv = env; vlmyclass = myclass; return vlrnum(vltable[index]); } JNIEXPORT jint JNICALL Java_qdbm_Villa_vlwritable(JNIEnv *env, jclass myclass, jint index) { vljnienv = env; vlmyclass = myclass; return vlwritable(vltable[index]); } JNIEXPORT jint JNICALL Java_qdbm_Villa_vlfatalerror(JNIEnv *env, jclass myclass, jint index) { vljnienv = env; vlmyclass = myclass; return vlfatalerror(vltable[index]); } JNIEXPORT jint JNICALL Java_qdbm_Villa_vlinode(JNIEnv *env, jclass myclass, jint index) { vljnienv = env; vlmyclass = myclass; return vlinode(vltable[index]); } JNIEXPORT jlong JNICALL Java_qdbm_Villa_vlmtime(JNIEnv *env, jclass myclass, jint index) { vljnienv = env; vlmyclass = myclass; return vlmtime(vltable[index]); } JNIEXPORT jint JNICALL Java_qdbm_Villa_vltranbegin(JNIEnv *env, jclass myclass, jint index) { vljnienv = env; vlmyclass = myclass; return vltranbegin(vltable[index]); } JNIEXPORT jint JNICALL Java_qdbm_Villa_vltrancommit(JNIEnv *env, jclass myclass, jint index) { vljnienv = env; vlmyclass = myclass; return vltrancommit(vltable[index]); } JNIEXPORT jint JNICALL Java_qdbm_Villa_vltranabort(JNIEnv *env, jclass myclass, jint index) { vljnienv = env; vlmyclass = myclass; return vltranabort(vltable[index]); } JNIEXPORT jint JNICALL Java_qdbm_Villa_vlremove(JNIEnv *env, jclass myclass, jstring name) { const char *tname; jboolean ic; int rv; tname = (*env)->GetStringUTFChars(env, name, &ic); rv = vlremove(tname); if(ic == JNI_TRUE) (*env)->ReleaseStringUTFChars(env, name, tname); return rv; } JNIEXPORT jint JNICALL Java_qdbm_VillaCursor_vlmulcurecode(JNIEnv *env, jclass myclass) { return Java_qdbm_Villa_vlecode(env, myclass); } JNIEXPORT jint JNICALL Java_qdbm_VillaCursor_vlmulcurnew(JNIEnv *env, jobject obj, jint index) { jclass cls; jfieldID fid; VLMULCUR *mulcur; if(!(mulcur = vlmulcuropen(vltable[index]))) return 0; cls = (*env)->GetObjectClass(env, obj); fid = (*env)->GetFieldID(env, cls, "coreptr", "J"); (*env)->SetLongField(env, obj, fid, (PTRNUM)mulcur); return 1; } JNIEXPORT void JNICALL Java_qdbm_VillaCursor_vlmulcurdelete(JNIEnv *env, jobject obj) { jclass cls; jfieldID fid; jlong coreptr; cls = (*env)->GetObjectClass(env, obj); fid = (*env)->GetFieldID(env, cls, "coreptr", "J"); coreptr = (*env)->GetLongField(env, obj, fid); printf("hoge\n"); vlmulcurclose((VLMULCUR *)(PTRNUM)coreptr); } JNIEXPORT jint JNICALL Java_qdbm_VillaCursor_vlmulcurfirst(JNIEnv *env, jobject obj, jint index) { jclass cls; jfieldID fid; jlong coreptr; cls = (*env)->GetObjectClass(env, obj); fid = (*env)->GetFieldID(env, cls, "coreptr", "J"); coreptr = (*env)->GetLongField(env, obj, fid); return vlmulcurfirst((VLMULCUR *)(PTRNUM)coreptr); } JNIEXPORT jint JNICALL Java_qdbm_VillaCursor_vlmulcurlast(JNIEnv *env, jobject obj, jint index) { jclass cls; jfieldID fid; jlong coreptr; cls = (*env)->GetObjectClass(env, obj); fid = (*env)->GetFieldID(env, cls, "coreptr", "J"); coreptr = (*env)->GetLongField(env, obj, fid); return vlmulcurlast((VLMULCUR *)(PTRNUM)coreptr); } JNIEXPORT jint JNICALL Java_qdbm_VillaCursor_vlmulcurprev(JNIEnv *env, jobject obj, jint index) { jclass cls; jfieldID fid; jlong coreptr; cls = (*env)->GetObjectClass(env, obj); fid = (*env)->GetFieldID(env, cls, "coreptr", "J"); coreptr = (*env)->GetLongField(env, obj, fid); return vlmulcurprev((VLMULCUR *)(PTRNUM)coreptr); } JNIEXPORT jint JNICALL Java_qdbm_VillaCursor_vlmulcurnext(JNIEnv *env, jobject obj, jint index) { jclass cls; jfieldID fid; jlong coreptr; cls = (*env)->GetObjectClass(env, obj); fid = (*env)->GetFieldID(env, cls, "coreptr", "J"); coreptr = (*env)->GetLongField(env, obj, fid); return vlmulcurnext((VLMULCUR *)(PTRNUM)coreptr); } JNIEXPORT jint JNICALL Java_qdbm_VillaCursor_vlmulcurjump(JNIEnv *env, jobject obj, jint index, jbyteArray key, jint ksiz, jint jmode) { jclass cls; jfieldID fid; jlong coreptr; jbyte *kbuf; jboolean ick; int rv; cls = (*env)->GetObjectClass(env, obj); fid = (*env)->GetFieldID(env, cls, "coreptr", "J"); coreptr = (*env)->GetLongField(env, obj, fid); kbuf = (*env)->GetByteArrayElements(env, key, &ick); rv = vlmulcurjump((VLMULCUR *)(PTRNUM)coreptr, (char *)kbuf, ksiz, getvljmode(jmode)); if(ick == JNI_TRUE) (*env)->ReleaseByteArrayElements(env, key, kbuf, JNI_ABORT); return rv; } JNIEXPORT jbyteArray JNICALL Java_qdbm_VillaCursor_vlmulcurkey(JNIEnv *env, jobject obj, jint index) { jclass cls; jfieldID fid; jlong coreptr; const char *key; int ksiz; jbyteArray kbuf; cls = (*env)->GetObjectClass(env, obj); fid = (*env)->GetFieldID(env, cls, "coreptr", "J"); coreptr = (*env)->GetLongField(env, obj, fid); key = vlmulcurkeycache((VLMULCUR *)(PTRNUM)coreptr, &ksiz); if(key){ kbuf = (*env)->NewByteArray(env, ksiz); (*env)->SetByteArrayRegion(env, kbuf, 0, ksiz, (jbyte *)key); } else { kbuf = NULL; } return kbuf; } JNIEXPORT jbyteArray JNICALL Java_qdbm_VillaCursor_vlmulcurval(JNIEnv *env, jobject obj, jint index) { jclass cls; jfieldID fid; jlong coreptr; const char *key; int ksiz; jbyteArray kbuf; cls = (*env)->GetObjectClass(env, obj); fid = (*env)->GetFieldID(env, cls, "coreptr", "J"); coreptr = (*env)->GetLongField(env, obj, fid); key = vlmulcurvalcache((VLMULCUR *)(PTRNUM)coreptr, &ksiz); if(key){ kbuf = (*env)->NewByteArray(env, ksiz); (*env)->SetByteArrayRegion(env, kbuf, 0, ksiz, (jbyte *)key); } else { kbuf = NULL; } return kbuf; } /************************************************************************************************* * private objects *************************************************************************************************/ static int getnewindex(void){ int i; for(i = 0; i < MAXOPEN; i++){ if(vltable[i] == NULL) return i; } return -1; } static int checkdup(const char *name){ struct stat sbuf; int i, inode; if(stat(name, &sbuf) == -1) return 0; inode = sbuf.st_ino; for(i = 0; i < MAXOPEN; i++){ if(vltable[i] != NULL && vlinode(vltable[i]) == inode) return -1; } return 0; } static int getvlomode(jint omode){ int vlomode; vlomode = VL_OREADER; if(omode & qdbm_Villa_OWRITER){ vlomode = VL_OWRITER; if(omode & qdbm_Villa_OCREAT) vlomode |= VL_OCREAT; if(omode & qdbm_Villa_OTRUNC) vlomode |= VL_OTRUNC; } if(omode & qdbm_Villa_ONOLCK) vlomode |= VL_ONOLCK; if(omode & qdbm_Villa_OLCKNB) vlomode |= VL_OLCKNB; if(omode & qdbm_Villa_OZCOMP) vlomode |= VL_OZCOMP; if(omode & qdbm_Villa_OYCOMP) vlomode |= VL_OYCOMP; if(omode & qdbm_Villa_OXCOMP) vlomode |= VL_OXCOMP; return vlomode; } static VLCFUNC getvlcmp(jint cmode){ switch(cmode){ case qdbm_Villa_CMPLEX: return VL_CMPLEX; case qdbm_Villa_CMPNUM: return VL_CMPNUM; case qdbm_Villa_CMPDEC: return VL_CMPDEC; case qdbm_Villa_CMPOBJ: return objcompare; } return NULL; } static int getvldmode(jint dmode){ switch(dmode){ case qdbm_Villa_DOVER: return VL_DOVER; case qdbm_Villa_DKEEP: return VL_DKEEP; case qdbm_Villa_DCAT: return VL_DCAT; case qdbm_Villa_DDUP: return VL_DDUP; case qdbm_Villa_DDUPR: return VL_DDUPR; } return -1; } static int getvljmode(jint jmode){ switch(jmode){ case qdbm_Villa_JFORWARD: return VL_JFORWARD; case qdbm_Villa_JBACKWARD: return VL_JBACKWARD; } return -1; } static int getvlcpmode(jint cpmode){ switch(cpmode){ case qdbm_Villa_CPCURRENT: return VL_CPCURRENT; case qdbm_Villa_CPBEFORE: return VL_CPBEFORE; case qdbm_Villa_CPAFTER: return VL_CPAFTER; } return -1; } static int objcompare(const char *aptr, int asiz, const char *bptr, int bsiz){ jmethodID mid; jbyteArray abuf, bbuf; mid = (*vljnienv)->GetStaticMethodID(vljnienv, vlmyclass, "objcompare", "([B[B)I"); abuf = (*vljnienv)->NewByteArray(vljnienv, asiz); (*vljnienv)->SetByteArrayRegion(vljnienv, abuf, 0, asiz, (jbyte *)aptr); bbuf = (*vljnienv)->NewByteArray(vljnienv, bsiz); (*vljnienv)->SetByteArrayRegion(vljnienv, bbuf, 0, bsiz, (jbyte *)bptr); return (*vljnienv)->CallStaticIntMethod(vljnienv, vlmyclass, mid, abuf, bbuf); } /* END OF FILE */ qdbm-1.8.78/java/Curia.java0000644000175000017500000007222010505671474014407 0ustar mikiomikio/************************************************************************************************* * Java API of Curia, the extended API of QDBM * Copyright (C) 2000-2006 Mikio Hirabayashi * This file is part of QDBM, Quick Database Manager. * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU * Lesser General Public License as published by the Free Software Foundation; either version * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * You should have received a copy of the GNU Lesser General Public License along with QDBM; if * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. *************************************************************************************************/ package qdbm; /** * The Java API of Curia, the extended API of QDBM. * This class depends on the native library `jqdbm'. */ public class Curia implements ADBM { //---------------------------------------------------------------- // error codes //---------------------------------------------------------------- /** error code: no error */ public static final int ENOERR = 0; /** error code: with fatal error */ public static final int EFATAL = 1; /** error code: invalid mode */ public static final int EMODE = 2; /** error code: broken database file */ public static final int EBROKEN = 3; /** error code: existing record */ public static final int EKEEP = 4; /** error code: no item found */ public static final int ENOITEM = 5; /** error code: memory allocation error */ public static final int EALLOC = 6; /** error code: memory mapping error */ public static final int EMAP = 7; /** error code: open error */ public static final int EOPEN = 8; /** error code: close error */ public static final int ECLOSE = 9; /** error code: trunc error */ public static final int ETRUNC = 10; /** error code: sync error */ public static final int ESYNC = 11; /** error code: stat error */ public static final int ESTAT = 12; /** error code: seek error */ public static final int ESEEK = 13; /** error code: read error */ public static final int EREAD = 14; /** error code: write error */ public static final int EWRITE = 15; /** error code: lock error */ public static final int ELOCK = 16; /** error code: unlink error */ public static final int EUNLINK = 17; /** error code: mkdir error */ public static final int EMKDIR = 18; /** error code: rmdir error */ public static final int ERMDIR = 19; /** error code: miscellaneous error */ public static final int EMISC = 20; //---------------------------------------------------------------- // open modes //---------------------------------------------------------------- /** open mode: open as a reader */ public static final int OREADER = 1 << 0; /** open mode: open as a writer */ public static final int OWRITER = 1 << 1; /** open mode: writer creating */ public static final int OCREAT = 1 << 2; /** open mode: writer truncating */ public static final int OTRUNC = 1 << 3; /** open mode: open without locking */ public static final int ONOLCK = 1 << 4; /** open mode: lock without blocking */ public static final int OLCKNB = 1 << 5; /** open mode: create as sparse files */ public static final int OSPARSE = 1 << 6; //---------------------------------------------------------------- // write modes //---------------------------------------------------------------- /** write mode: overwrite the existing value */ public static final int DOVER = 0; /** write mode: keep the existing value */ public static final int DKEEP = 1; /** write mode: concatenate values */ public static final int DCAT = 2; //---------------------------------------------------------------- // static initializer //---------------------------------------------------------------- static { try { System.loadLibrary("jqdbm"); } catch(UnsatisfiedLinkError e){ e.printStackTrace(); } crinit(); } //---------------------------------------------------------------- // public static methods //---------------------------------------------------------------- /** * Get the version information. * @return a string of the version information. */ public static synchronized String version(){ return crversion(); } /** * Get an error message. * @param ecode an error code. * @return the message string of the error code. */ public static synchronized String errmsg(int ecode){ return crerrmsg(ecode); } /** * Remove a database directory. * @param name the name of a database directory. * @throws CuriaException if an error occurs. */ public static void remove(String name) throws CuriaException { synchronized(ADBM.class){ if(crremove(name) == 0) throw new CuriaException(crecode()); } } /** * Retrieve a record directly from a database directory. * @param name the name of a database directory. * @param key a byte array of a key. * @throws CuriaException if an error occurs or no record corresponds. * @note Although this method can be used even while the database directory is locked by * another process, it is not assured that recent updated is reflected. */ public static byte[] snaffle(String name, byte[] key) throws CuriaException { synchronized(ADBM.class){ byte[] val = crsnaffle(name, key, key.length); if(val == null) throw new CuriaException(crecode()); return val; } } //---------------------------------------------------------------- // instance fields //---------------------------------------------------------------- /** Whether to repress frequent exceptions. */ public boolean silent; /** Index of the native table for database handles. */ private int index; //---------------------------------------------------------------- // public or protected methods //---------------------------------------------------------------- /** * Get the database handle. * @param name the name of a database directory. * @param omode the connection mode: `Curia.OWRITER' as a writer, `Curia.OREADER' as * a reader. If the mode is `Curia.OWRITER', the following may be added by bitwise or: * `Curia.OCREAT', which means it creates a new database if not exist, `Curia.OTRUNC', * which means it creates a new database regardless if one exists. Both of `Curia.OREADER' * and `Curia.OWRITER' can be added to by bitwise or: `Curia.ONOLCK', which means it opens a * database directory without file locking, or `Curia.OLCKNB', which means locking is performed * without blocking. `Curia.OCREAT' can be added to by bitwise or: `Curia.OSPARSE', which * means it creates database files as sparse files. * @param bnum the number of elements of the each bucket array. If it is not more than 0, * the default value is specified. The size of each bucket array is determined on creating, * and can not be changed except for by optimization of the database. Suggested size of each * bucket array is about from 0.5 to 4 times of the number of all records to store. * @param dnum the number of division of the database. If it is not more than 0, the default * value is specified. The number of division can not be changed from the initial value. The * max number of division is 512. * @throws CuriaException if an error occurs. * @note While connecting as a writer, an exclusive lock is invoked to the database directory. * While connecting as a reader, a shared lock is invoked to the database directory. * The thread blocks until the lock is achieved. If `Curia.ONOLCK' is used, the application * is responsible for exclusion control. */ public Curia(String name, int omode, int bnum, int dnum) throws CuriaException { synchronized(ADBM.class){ silent = false; if((index = cropen(name, omode, bnum, dnum)) == -1) throw new CuriaException(crecode()); } } /** * Get the database handle as a reader. * The same as `Curia(name, Curia.OREADER, -1)'. * @see #Curia(java.lang.String, int, int, int) */ public Curia(String name) throws CuriaException { this(name, OREADER, -1, -1); } /** * Release the resources. * @note If the database handle is not closed yet, it is closed. Every database should be * closed explicitly. Do not cast the duty on the gerbage collection. */ protected void finalize() throws Throwable { try { if(index < 0) return; synchronized(ADBM.class){ crclose(index); index = -1; } } finally { super.finalize(); } } /** * Close the database handle. * @throws CuriaException if an error occurs. * @note Updating a database is assured to be written when the handle is closed. If a * writer opens a database but does not close it appropriately, the database will be broken. */ public void close() throws CuriaException { if(index < 0) throw new CuriaException(); synchronized(ADBM.class){ int rv = crclose(index); index = -1; if(rv == 0) throw new CuriaException(crecode()); } } /** * Store a record. * @param key a byte array of a key. * @param val a byte array of a value. * @param dmode behavior when the key overlaps, by the following values: `Curia.DOVER', * which means the specified value overwrites the existing one, `Curia.DKEEP', which means the * existing value is kept, `Curia.DCAT', which means the specified value is concatenated at * the end of the existing value. * @return always true. However, if the silent flag is true and replace is cancelled, false is * returned instead of exception. * @throws CuriaException if an error occurs or replace is cancelled. */ public boolean put(byte[] key, byte[] val, int dmode) throws CuriaException { if(index < 0) throw new CuriaException(); synchronized(ADBM.class){ if(crput(index, key, key.length, val, val.length, dmode) == 0){ if(silent && crecode() == EKEEP) return false; throw new CuriaException(crecode()); } return true; } } /** * Store a record with overwrite. * The same as `put(key, val, Curia.DOVER)'. * @see #put(byte[], byte[], int) */ public boolean put(byte[] key, byte[] val) throws CuriaException { return put(key, val, DOVER); } /** * Delete a record. * @param key a byte array of a key. * @return always true. However, if the silent flag is true and no record corresponds, false * is returned instead of exception. * @throws CuriaException if an error occurs or no record corresponds. */ public boolean out(byte[] key) throws CuriaException { if(index < 0) throw new CuriaException(); synchronized(ADBM.class){ if(crout(index, key, key.length) == 0){ if(silent && crecode() == ENOITEM) return false; throw new CuriaException(crecode()); } return true; } } /** * Retrieve a record. * @param key a byte array of a key. * @param start the array index of the beginning of the value to be read. * @param max the max size to read with. If it is negative, the size is unlimited. * @return a byte array of the value of the corresponding record. If the silent flag is true * and no record corresponds, `null' is returned instead of exception. * @throws CuriaException if an error occurs, no record corresponds, or the size of the value * of the corresponding record is less than the index specified by the parameter `start'. */ public byte[] get(byte[] key, int start, int max) throws CuriaException { if(index < 0) throw new CuriaException(); synchronized(ADBM.class){ byte[] val = crget(index, key, key.length, start, max); if(val == null){ if(silent && crecode() == ENOITEM) return null; throw new CuriaException(crecode()); } return val; } } /** * Retrieve whole value of a record. * The same as `get(key, 0, -1)'. * @see #get(byte[], int, int) */ public byte[] get(byte[] key) throws CuriaException { return get(key, 0, -1); } /** * Get the size of the value of a record. * @param key a byte array of a key. * @return the size of the value of the corresponding record. If the silent flag is true and * no record corresponds, -1 is returned instead of exception. * @throws CuriaException if an error occurs or no record corresponds. * @note Because this method does not read the entity of a record, it is faster than `get'. */ public int vsiz(byte[] key) throws CuriaException { if(index < 0) throw new CuriaException(); synchronized(ADBM.class){ int rv = crvsiz(index, key, key.length); if(rv == -1){ if(silent && crecode() == ENOITEM) return -1; throw new CuriaException(crecode()); } return rv; } } /** * Initialize the iterator of the database handle. * @throws CuriaException if an error occurs. * @note The iterator is used in order to access the key of every record stored in a database. */ public void iterinit() throws CuriaException { if(index < 0) throw new CuriaException(); synchronized(ADBM.class){ if(criterinit(index) == 0) throw new CuriaException(crecode()); } } /** * Get the next key of the iterator. * @return a byte array of the key of the next record. If the silent flag is true and no * record corresponds, `null' is returned instead of exception. * @throws CuriaException if an error occurs or no record corresponds. * @note It is possible to access every record by iteration of calling this method. * However, it is not assured if updating the database is occurred while the iteration. * Besides, the order of this traversal access method is arbitrary, so it is not assured * that the order of storing matches the one of the traversal access. */ public byte[] iternext() throws CuriaException { if(index < 0) throw new CuriaException(); synchronized(ADBM.class){ byte[] val = criternext(index); if(val == null){ if(silent && crecode() == ENOITEM) return null; throw new CuriaException(crecode()); } return val; } } /** * Set alignment of the database handle. * @param align the basic size of alignment. * @throws CuriaException if an error occurs. * @note If alignment is set to a database, the efficiency of overwriting values is improved. * The size of alignment is suggested to be average size of the values of the records to be * stored. If alignment is positive, padding whose size is multiple number of the alignment * is placed. If alignment is negative, as `vsiz' is the size of a value, the size of padding * is calculated with `(vsiz / pow(2, abs(align) - 1))'. Because alignment setting is not * saved in a database, you should specify alignment every opening a database. */ public void setalign(int align) throws CuriaException { if(index < 0) throw new CuriaException(); synchronized(ADBM.class){ if(crsetalign(index, align) == 0) throw new CuriaException(crecode()); } } /** * Set the size of the free block pool. * @param size the size of the free block pool of a database. * @throws CuriaException if an error occurs. * @note The default size of the free block pool is 16. If the size is greater, the space * efficiency of overwriting values is improved with the time efficiency sacrificed. */ public void setfbpsiz(int size) throws CuriaException { if(index < 0) throw new CuriaException(); synchronized(ADBM.class){ if(crsetfbpsiz(index, size) == 0) throw new CuriaException(crecode()); } } /** * Synchronize updating contents with the files and the devices. * @throws CuriaException if an error occurs. * @note This method is useful when another process uses the connected database directory. */ public void sync() throws CuriaException { if(index < 0) throw new CuriaException(); synchronized(ADBM.class){ if(crsync(index) == 0) throw new CuriaException(crecode()); } } /** * Optimize the database. * @param bnum the number of the elements of each bucket array. If it is not more than 0, the * default value is specified. * @throws CuriaException if an error occurs. * @note In an alternating succession of deleting and storing with overwrite or concatenate, * dispensable regions accumulate. This method is useful to do away with them. */ public void optimize(int bnum) throws CuriaException { if(index < 0) throw new CuriaException(); synchronized(ADBM.class){ if(croptimize(index, bnum) == 0) throw new CuriaException(crecode()); } } /** * Get the name of the database. * @return the string of the name of the database. * @throws CuriaException if an error occurs. */ public String name() throws CuriaException { if(index < 0) throw new CuriaException(); synchronized(ADBM.class){ String buf = crname(index); if(buf == null) throw new CuriaException(crecode()); return buf; } } /** * Get the total size of the database files. * @return the total size of the database files. * @throws CuriaException if an error occurs. */ public long fsiz() throws CuriaException { if(index < 0) throw new CuriaException(); synchronized(ADBM.class){ long rv = (long)crfsizd(index); if(rv == -1) throw new CuriaException(crecode()); return rv; } } /** * Get the total number of the elements of each bucket array. * @return the total number of the elements of each bucket array. * @throws CuriaException if an error occurs. */ public int bnum() throws CuriaException { if(index < 0) throw new CuriaException(); synchronized(ADBM.class){ int rv = crbnum(index); if(rv == -1) throw new CuriaException(crecode()); return rv; } } /** * Get the total number of the used elements of each bucket array. * @return the total number of the used elements of each bucket array. * @throws CuriaException if an error occurs. * @note This method is inefficient because it accesses all elements of each bucket array. */ public int busenum() throws CuriaException { if(index < 0) throw new CuriaException(); synchronized(ADBM.class){ int rv = crbusenum(index); if(rv == -1) throw new CuriaException(crecode()); return rv; } } /** * Get the number of the records stored in the database. * @return the number of the records stored in the database. * @throws CuriaException if an error occurs. */ public int rnum() throws CuriaException { if(index < 0) throw new CuriaException(); synchronized(ADBM.class){ int rv = crrnum(index); if(rv == -1) throw new CuriaException(crecode()); return rv; } } /** * Check whether the database handle is a writer or not. * @return true if the handle is a writer, false if not. * @throws CuriaException if an error occurs. */ public boolean writable() throws CuriaException { if(index < 0) throw new CuriaException(); synchronized(ADBM.class){ return crwritable(index) == 0 ? false : true; } } /** * Check whether the database has a fatal error or not. * @return true if the database has a fatal error, false if not. * @throws CuriaException if an error occurs. */ public boolean fatalerror() throws CuriaException { if(index < 0) throw new CuriaException(); synchronized(ADBM.class){ return crfatalerror(index) == 0 ? false : true; } } /** * Get the inode number of the database. * @return the inode number of the database directory. * @throws CuriaException if an error occurs. */ public int inode() throws CuriaException { if(index < 0) throw new CuriaException(); synchronized(ADBM.class){ return crinode(index); } } /** * Get the last modified time of the database. * @return the last modified time of the database. * @throws CuriaException if an error occurs. */ public long mtime() throws CuriaException { if(index < 0) throw new CuriaException(); synchronized(ADBM.class){ return crmtime(index); } } /** * Store a large object. * @param key a byte array of a key. * @param val a byte array of a value. * @param dmode behavior when the key overlaps, by the following values: `Curia.DOVER', * which means the specified value overwrites the existing one, `Curia.DKEEP', which means the * existing value is kept, `Curia.DCAT', which means the specified value is concatenated at * the end of the existing value. * @return always true. However, if the silent flag is true and replace is cancelled, false is * returned instead of exception. * @throws CuriaException if an error occurs or replace is cancelled. */ public boolean putlob(byte[] key, byte[] val, int dmode) throws CuriaException { if(index < 0) throw new CuriaException(); synchronized(ADBM.class){ if(crputlob(index, key, key.length, val, val.length, dmode) == 0){ if(silent && crecode() == EKEEP) return false; throw new CuriaException(crecode()); } return true; } } /** * Store a large object with overwrite. * The same as `putlob(key, val, Curia.DOVER)'. * @see #put(byte[], byte[], int) */ public boolean putlob(byte[] key, byte[] val) throws CuriaException { return putlob(key, val, DOVER); } /** * Delete a large object. * @param key a byte array of a key. * @return always true. However, if the silent flag is true and no record corresponds, false * is returned instead of exception. * @throws CuriaException if an error occurs or no large object corresponds. */ public boolean outlob(byte[] key) throws CuriaException { if(index < 0) throw new CuriaException(); synchronized(ADBM.class){ if(croutlob(index, key, key.length) == 0){ if(silent && crecode() == ENOITEM) return false; throw new CuriaException(crecode()); } return true; } } /** * Retrieve a large object. * @param key a byte array of a key. * @param start the array index of the beginning of the value to be read. * @param max the max size to be read. If it is negative, the size to read is unlimited. * @return a byte array of the value of the corresponding large object. If the silent flag is * true and no record corresponds, `null' is returned instead of exception. * @throws CuriaException if an error occurs, no large object corresponds or the size of the * value of the corresponding is less than the index specified by the parameter `start'. */ public byte[] getlob(byte[] key, int start, int max) throws CuriaException { if(index < 0) throw new CuriaException(); synchronized(ADBM.class){ byte[] val = crgetlob(index, key, key.length, start, max); if(val == null){ if(silent && crecode() == ENOITEM) return null; throw new CuriaException(crecode()); } return val; } } /** * Retrieve whole value of a large object. * The same as `get(key, 0, -1)'. * @see #get(byte[], int, int) */ public byte[] getlob(byte[] key) throws CuriaException { return getlob(key, 0, -1); } /** * Get the size of the value of a large object. * @param key a byte array of a key. * @return the size of the value of the corresponding large object. * @throws CuriaException if an error occurs or no large object corresponds. * @note Because this method does not read the entity of a large object, it is faster * than `get'. */ public int vsizlob(byte[] key) throws CuriaException { if(index < 0) throw new CuriaException(); synchronized(ADBM.class){ int rv = crvsiz(index, key, key.length); if(rv == -1) throw new CuriaException(crecode()); return rv; } } /** * Get the number of the large objects stored in the database. * @return the number of the large objects stored in the database. * @throws CuriaException if an error occurs. */ public int rnumlob() throws CuriaException { if(index < 0) throw new CuriaException(); synchronized(ADBM.class){ int rv = crrnumlob(index); if(rv == -1) throw new CuriaException(crecode()); return rv; } } /** * Store a record. * @param key a byte array of a key. * @param val a byte array of a value. * @param replace whether the existing value is to be overwritten or not. * @throws CuriaException if an error occurs or replace is cancelled. */ public void store(byte[] key, byte[] val, boolean replace) throws CuriaException { if(!put(key, val, replace ? DOVER : DKEEP)) throw new CuriaException(EKEEP); } /** * Delete a record. * @param key a byte array of a key. * @throws CuriaException if an error occurs or no record corresponds. */ public void delete(byte[] key) throws CuriaException { if(!out(key)) throw new CuriaException(ENOITEM); } /** * Fetch a record. * @param key a byte array of a key. * @return a byte array of the value of the corresponding record. * @throws CuriaException if an error occurs or no record corresponds. */ public byte[] fetch(byte[] key) throws CuriaException { byte[] vbuf = get(key, 0, -1); if(vbuf == null) throw new CuriaException(ENOITEM); return vbuf; } /** * Get the first key. * @return a byte array of the key of the first record. * @throws CuriaException if an error occurs or no record corresponds. */ public byte[] firstkey() throws CuriaException { iterinit(); byte[] kbuf = iternext(); if(kbuf == null) throw new CuriaException(ENOITEM); return kbuf; } /** * Get the next key. * @return a byte array of the key of the next record. * @throws CuriaException if an error occurs or no record corresponds. */ public byte[] nextkey() throws CuriaException { byte[] kbuf = iternext(); if(kbuf == null) throw new CuriaException(ENOITEM); return kbuf; } /** * Check whether a fatal error occured or not. * @return true if the database has a fatal error, false if not. * @throws CuriaException if an error occurs. */ public boolean error() throws CuriaException { return fatalerror(); } //---------------------------------------------------------------- // native methods //---------------------------------------------------------------- private static synchronized final native void crinit(); private static synchronized final native String crversion(); private static synchronized final native int crecode(); private static synchronized final native String crerrmsg(int ecode); private static synchronized final native int cropen(String name, int omode, int bnum, int dnum); private static synchronized final native int crclose(int index); private static synchronized final native int crput(int index, byte[] key, int ksiz, byte[] val, int vsiz, int dmode); private static synchronized final native int crout(int index, byte[] key, int ksiz); private static synchronized final native byte[] crget(int index, byte[] key, int ksiz, int start, int max); private static synchronized final native int crvsiz(int index, byte[] key, int ksiz); private static synchronized final native int criterinit(int index); private static synchronized final native byte[] criternext(int index); private static synchronized final native int crsetalign(int index, int align); private static synchronized final native int crsetfbpsiz(int index, int size); private static synchronized final native int crsync(int index); private static synchronized final native int croptimize(int index, int bnum); private static synchronized final native String crname(int index); private static synchronized final native double crfsizd(int index); private static synchronized final native int crbnum(int index); private static synchronized final native int crbusenum(int index); private static synchronized final native int crrnum(int index); private static synchronized final native int crwritable(int index); private static synchronized final native int crfatalerror(int index); private static synchronized final native int crinode(int index); private static synchronized final native long crmtime(int index); private static synchronized final native int crputlob(int index, byte[] key, int ksiz, byte[] val, int vsiz, int dmode); private static synchronized final native int croutlob(int index, byte[] key, int ksiz); private static synchronized final native byte[] crgetlob(int index, byte[] key, int ksiz, int start, int max); private static synchronized final native int crvsizlob(int index, byte[] key, int ksiz); private static synchronized final native int crrnumlob(int index); private static synchronized final native int crremove(String name); private static synchronized final native byte[] crsnaffle(String name, byte[] key, int ksiz); } /* END OF FILE */ qdbm-1.8.78/java/qdbm_Depot.h0000644000175000017500000001426310431666727014736 0ustar mikiomikio/* DO NOT EDIT THIS FILE - it is machine generated */ #include /* Header for class qdbm_Depot */ #ifndef _Included_qdbm_Depot #define _Included_qdbm_Depot #ifdef __cplusplus extern "C" { #endif #undef qdbm_Depot_ENOERR #define qdbm_Depot_ENOERR 0L #undef qdbm_Depot_EFATAL #define qdbm_Depot_EFATAL 1L #undef qdbm_Depot_EMODE #define qdbm_Depot_EMODE 2L #undef qdbm_Depot_EBROKEN #define qdbm_Depot_EBROKEN 3L #undef qdbm_Depot_EKEEP #define qdbm_Depot_EKEEP 4L #undef qdbm_Depot_ENOITEM #define qdbm_Depot_ENOITEM 5L #undef qdbm_Depot_EALLOC #define qdbm_Depot_EALLOC 6L #undef qdbm_Depot_EMAP #define qdbm_Depot_EMAP 7L #undef qdbm_Depot_EOPEN #define qdbm_Depot_EOPEN 8L #undef qdbm_Depot_ECLOSE #define qdbm_Depot_ECLOSE 9L #undef qdbm_Depot_ETRUNC #define qdbm_Depot_ETRUNC 10L #undef qdbm_Depot_ESYNC #define qdbm_Depot_ESYNC 11L #undef qdbm_Depot_ESTAT #define qdbm_Depot_ESTAT 12L #undef qdbm_Depot_ESEEK #define qdbm_Depot_ESEEK 13L #undef qdbm_Depot_EREAD #define qdbm_Depot_EREAD 14L #undef qdbm_Depot_EWRITE #define qdbm_Depot_EWRITE 15L #undef qdbm_Depot_ELOCK #define qdbm_Depot_ELOCK 16L #undef qdbm_Depot_EUNLINK #define qdbm_Depot_EUNLINK 17L #undef qdbm_Depot_EMKDIR #define qdbm_Depot_EMKDIR 18L #undef qdbm_Depot_ERMDIR #define qdbm_Depot_ERMDIR 19L #undef qdbm_Depot_EMISC #define qdbm_Depot_EMISC 20L #undef qdbm_Depot_OREADER #define qdbm_Depot_OREADER 1L #undef qdbm_Depot_OWRITER #define qdbm_Depot_OWRITER 2L #undef qdbm_Depot_OCREAT #define qdbm_Depot_OCREAT 4L #undef qdbm_Depot_OTRUNC #define qdbm_Depot_OTRUNC 8L #undef qdbm_Depot_ONOLCK #define qdbm_Depot_ONOLCK 16L #undef qdbm_Depot_OLCKNB #define qdbm_Depot_OLCKNB 32L #undef qdbm_Depot_OSPARSE #define qdbm_Depot_OSPARSE 64L #undef qdbm_Depot_DOVER #define qdbm_Depot_DOVER 0L #undef qdbm_Depot_DKEEP #define qdbm_Depot_DKEEP 1L #undef qdbm_Depot_DCAT #define qdbm_Depot_DCAT 2L /* Inaccessible static: class_00024qdbm_00024ADBM */ /* * Class: qdbm_Depot * Method: dpinit * Signature: ()V */ JNIEXPORT void JNICALL Java_qdbm_Depot_dpinit (JNIEnv *, jclass); /* * Class: qdbm_Depot * Method: dpversion * Signature: ()Ljava/lang/String; */ JNIEXPORT jstring JNICALL Java_qdbm_Depot_dpversion (JNIEnv *, jclass); /* * Class: qdbm_Depot * Method: dpecode * Signature: ()I */ JNIEXPORT jint JNICALL Java_qdbm_Depot_dpecode (JNIEnv *, jclass); /* * Class: qdbm_Depot * Method: dperrmsg * Signature: (I)Ljava/lang/String; */ JNIEXPORT jstring JNICALL Java_qdbm_Depot_dperrmsg (JNIEnv *, jclass, jint); /* * Class: qdbm_Depot * Method: dpopen * Signature: (Ljava/lang/String;II)I */ JNIEXPORT jint JNICALL Java_qdbm_Depot_dpopen (JNIEnv *, jclass, jstring, jint, jint); /* * Class: qdbm_Depot * Method: dpclose * Signature: (I)I */ JNIEXPORT jint JNICALL Java_qdbm_Depot_dpclose (JNIEnv *, jclass, jint); /* * Class: qdbm_Depot * Method: dpput * Signature: (I[BI[BII)I */ JNIEXPORT jint JNICALL Java_qdbm_Depot_dpput (JNIEnv *, jclass, jint, jbyteArray, jint, jbyteArray, jint, jint); /* * Class: qdbm_Depot * Method: dpout * Signature: (I[BI)I */ JNIEXPORT jint JNICALL Java_qdbm_Depot_dpout (JNIEnv *, jclass, jint, jbyteArray, jint); /* * Class: qdbm_Depot * Method: dpget * Signature: (I[BIII)[B */ JNIEXPORT jbyteArray JNICALL Java_qdbm_Depot_dpget (JNIEnv *, jclass, jint, jbyteArray, jint, jint, jint); /* * Class: qdbm_Depot * Method: dpvsiz * Signature: (I[BI)I */ JNIEXPORT jint JNICALL Java_qdbm_Depot_dpvsiz (JNIEnv *, jclass, jint, jbyteArray, jint); /* * Class: qdbm_Depot * Method: dpiterinit * Signature: (I)I */ JNIEXPORT jint JNICALL Java_qdbm_Depot_dpiterinit (JNIEnv *, jclass, jint); /* * Class: qdbm_Depot * Method: dpiternext * Signature: (I)[B */ JNIEXPORT jbyteArray JNICALL Java_qdbm_Depot_dpiternext (JNIEnv *, jclass, jint); /* * Class: qdbm_Depot * Method: dpsetalign * Signature: (II)I */ JNIEXPORT jint JNICALL Java_qdbm_Depot_dpsetalign (JNIEnv *, jclass, jint, jint); /* * Class: qdbm_Depot * Method: dpsetfbpsiz * Signature: (II)I */ JNIEXPORT jint JNICALL Java_qdbm_Depot_dpsetfbpsiz (JNIEnv *, jclass, jint, jint); /* * Class: qdbm_Depot * Method: dpsync * Signature: (I)I */ JNIEXPORT jint JNICALL Java_qdbm_Depot_dpsync (JNIEnv *, jclass, jint); /* * Class: qdbm_Depot * Method: dpoptimize * Signature: (II)I */ JNIEXPORT jint JNICALL Java_qdbm_Depot_dpoptimize (JNIEnv *, jclass, jint, jint); /* * Class: qdbm_Depot * Method: dpname * Signature: (I)Ljava/lang/String; */ JNIEXPORT jstring JNICALL Java_qdbm_Depot_dpname (JNIEnv *, jclass, jint); /* * Class: qdbm_Depot * Method: dpfsiz * Signature: (I)I */ JNIEXPORT jint JNICALL Java_qdbm_Depot_dpfsiz (JNIEnv *, jclass, jint); /* * Class: qdbm_Depot * Method: dpbnum * Signature: (I)I */ JNIEXPORT jint JNICALL Java_qdbm_Depot_dpbnum (JNIEnv *, jclass, jint); /* * Class: qdbm_Depot * Method: dpbusenum * Signature: (I)I */ JNIEXPORT jint JNICALL Java_qdbm_Depot_dpbusenum (JNIEnv *, jclass, jint); /* * Class: qdbm_Depot * Method: dprnum * Signature: (I)I */ JNIEXPORT jint JNICALL Java_qdbm_Depot_dprnum (JNIEnv *, jclass, jint); /* * Class: qdbm_Depot * Method: dpwritable * Signature: (I)I */ JNIEXPORT jint JNICALL Java_qdbm_Depot_dpwritable (JNIEnv *, jclass, jint); /* * Class: qdbm_Depot * Method: dpfatalerror * Signature: (I)I */ JNIEXPORT jint JNICALL Java_qdbm_Depot_dpfatalerror (JNIEnv *, jclass, jint); /* * Class: qdbm_Depot * Method: dpinode * Signature: (I)I */ JNIEXPORT jint JNICALL Java_qdbm_Depot_dpinode (JNIEnv *, jclass, jint); /* * Class: qdbm_Depot * Method: dpmtime * Signature: (I)J */ JNIEXPORT jlong JNICALL Java_qdbm_Depot_dpmtime (JNIEnv *, jclass, jint); /* * Class: qdbm_Depot * Method: dpremove * Signature: (Ljava/lang/String;)I */ JNIEXPORT jint JNICALL Java_qdbm_Depot_dpremove (JNIEnv *, jclass, jstring); /* * Class: qdbm_Depot * Method: dpsnaffle * Signature: (Ljava/lang/String;[BI)[B */ JNIEXPORT jbyteArray JNICALL Java_qdbm_Depot_dpsnaffle (JNIEnv *, jclass, jstring, jbyteArray, jint); #ifdef __cplusplus } #endif #endif qdbm-1.8.78/java/overview0000644000175000017500000000340511426314470014262 0ustar mikiomikio/** * @mainpage *

QDBM is a library of routines for managing a database. The database is a simple data file containing records, each is a pair of a key and a value. Every key and value is serial bytes with variable length. Both binary data and character string can be used as a key and a value. There is neither concept of data tables nor data types. Records are organazed in hash table or B+ tree.

*

As for database of hash table, each key must be unique within a database, so it is impossible to store two or more records with a key overlaps. The following access methods are provided to the database: storing a record with a key and a value, deleting a record by a key, retrieving a record by a key. Moreover, traversal access to every key are provided, although the order is arbitrary. These access methods are similar to ones of DBM (or its followers, NDBM and GDBM) library defined in the UNIX standard. QDBM is an alternative for DBM because of its higher performance.

*

As for database of B+ tree, records whose keys are duplicated can be stored. Access methods of storing, deleting and retrieving are provided as with the database of hash table. Records are stored in order by a comparing function assigned by a user. It is possible to access each record with the cursor in ascending or descending order. According to this mechanism, forward matching search for strings and range search for integers are realized. Moreover, transaction is available in database of B+ tree.

*

This package is Java API for QDBM. This package contains native methods which are depends on native libraries of QDBM. Each class is packaged in `qdbm'.

*

Refer to `http://fallabs.com/qdbm/' for more information.

*/ qdbm-1.8.78/java/jspex-ja.html0000644000175000017500000004227411426311633015105 0ustar mikiomikio Specifications of QDBM for Java (Japanese)

QDBM付属Java用API仕様書

Copyright (C) 2000-2006 Mikio Hirabayashi
Last Update: Thu, 26 Oct 2006 15:00:20 +0900

目次

  1. 概è¦
  2. インストール
  3. 環境設定
  4. サンプルコード
  5. ãƒã‚°

概è¦

QDBMã«ã¯Java言語用ã®APIãŒã‚る。QDBMã®åŸºæœ¬APIã¨æ‹¡å¼µAPIã¨ä¸Šç´šAPIã®é–¢æ•°ç¾¤ã‚’Javaã®ã‚¯ãƒ©ã‚¹æ©Ÿæ§‹ã‚’用ã„ã¦ã‚«ãƒ—セル化ã—ã€ã‹ã¤ã‚¹ãƒ¬ãƒƒãƒ‰ã‚»ãƒ¼ãƒ•ã«ã—ãŸã‚‚ã®ã§ã‚る。C言語ã®APIã‚’Java Native Interfaceを介ã—ã¦å‘¼ã³å‡ºã™ã‚ˆã†ã«å®Ÿè£…ã•れã¦ã„る。

基本APIã¯ãƒ•ァイルを用ã„ã¦ãƒãƒƒã‚·ãƒ¥ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’実ç¾ã™ã‚‹ã€‚クラス `Depot' ã®ã‚³ãƒ³ã‚¹ãƒˆãƒ©ã‚¯ã‚¿ã«ã‚ˆã£ã¦ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルãŒé–‹ã‹ã‚Œã‚‹ã€‚データベースを閉ã˜ã‚‹ã«ã¯ãƒ¡ã‚½ãƒƒãƒ‰ `close' を呼ã¶ã€‚ファイナライザã§ã‚‚データベースを閉ã˜ã‚ˆã†ã¨ã™ã‚‹ãŒã€ãれã«é ¼ã£ã¦ã¯ãªã‚‰ãªã„。メソッド `put' ã¯ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’追加ã™ã‚‹ãŸã‚ã«ç”¨ã„る。メソッド `out' ã¯ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’削除ã™ã‚‹ãŸã‚ã«ç”¨ã„る。メソッド `get' ã¯ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’検索ã™ã‚‹ãŸã‚ã«ç”¨ã„る。ãã®ä»–ã«ã‚‚ã€C言語ã®åŸºæœ¬APIã¨ã»ã¼åŒã˜æ“作を利用ã™ã‚‹ã“ã¨ãŒã§ãる。å„メソッドã¯ã‚¨ãƒ©ãƒ¼æ™‚ã«ã‚¯ãƒ©ã‚¹ `DepotException' ã®ã‚¤ãƒ³ã‚¹ã‚¿ãƒ³ã‚¹ã‚’投ã’る。

æ‹¡å¼µAPIã¯ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã¨è¤‡æ•°ã®ãƒ•ァイルを用ã„ã¦ãƒãƒƒã‚·ãƒ¥ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’実ç¾ã™ã‚‹ã€‚クラス `Curia' ã®ã‚³ãƒ³ã‚¹ãƒˆãƒ©ã‚¯ã‚¿ã«ã‚ˆã£ã¦ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªãŒé–‹ã‹ã‚Œã‚‹ã€‚データベースを閉ã˜ã‚‹ã«ã¯ãƒ¡ã‚½ãƒƒãƒ‰ `close' を呼ã¶ã€‚ファイナライザã§ã‚‚データベースを閉ã˜ã‚ˆã†ã¨ã™ã‚‹ãŒã€ãれã«é ¼ã£ã¦ã¯ãªã‚‰ãªã„。メソッド `put' ã¯ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’追加ã™ã‚‹ãŸã‚ã«ç”¨ã„る。メソッド `out' ã¯ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’削除ã™ã‚‹ãŸã‚ã«ç”¨ã„る。メソッド `get' ã¯ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’検索ã™ã‚‹ãŸã‚ã«ç”¨ã„る。ãã®ä»–ã«ã‚‚ã€Cè¨€èªžã®æ‹¡å¼µAPIã¨ã»ã¼åŒã˜æ“作を利用ã™ã‚‹ã“ã¨ãŒã§ãる。å„メソッドã¯ã‚¨ãƒ©ãƒ¼æ™‚ã«ã‚¯ãƒ©ã‚¹ `CuriaException' ã®ã‚¤ãƒ³ã‚¹ã‚¿ãƒ³ã‚¹ã‚’投ã’る。

上級APIã¯ãƒ•ァイルを用ã„ã¦B+木データベースを実ç¾ã™ã‚‹ã€‚クラス `Villa' ã®ã‚³ãƒ³ã‚¹ãƒˆãƒ©ã‚¯ã‚¿ã«ã‚ˆã£ã¦ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルãŒé–‹ã‹ã‚Œã‚‹ã€‚データベースを閉ã˜ã‚‹ã«ã¯ãƒ¡ã‚½ãƒƒãƒ‰ `close' を呼ã¶ã€‚ファイナライザã§ã‚‚データベースを閉ã˜ã‚ˆã†ã¨ã™ã‚‹ãŒã€ãれã«é ¼ã£ã¦ã¯ãªã‚‰ãªã„。メソッド `put' ã¯ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’追加ã™ã‚‹ãŸã‚ã«ç”¨ã„る。メソッド `out' ã¯ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’削除ã™ã‚‹ãŸã‚ã«ç”¨ã„る。メソッド `get' ã¯ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’検索ã™ã‚‹ãŸã‚ã«ç”¨ã„る。ãã®ä»–ã«ã‚‚ã€C言語ã®ä¸Šç´šAPIã¨ã»ã¼åŒã˜æ“作を利用ã™ã‚‹ã“ã¨ãŒã§ãる。å„メソッドã¯ã‚¨ãƒ©ãƒ¼æ™‚ã«ã‚¯ãƒ©ã‚¹ `VillaException' ã®ã‚¤ãƒ³ã‚¹ã‚¿ãƒ³ã‚¹ã‚’投ã’る。

`Depot' 㨠`Curia' 㨠`Villa' ã¯ã‚¤ãƒ³ã‚¿ãƒ•ェース `ADBM' を実装ã™ã‚‹ã€‚ã“ã®ã‚¤ãƒ³ã‚¿ãƒ•ェースã¯UNIX標準ã®DBMã¨åŒæ§˜ã®æ©Ÿèƒ½ã‚’æŒã¤ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒžãƒãƒ¼ã‚¸ãƒ£ã‚’抽象化ã—ãŸã‚‚ã®ã§ã‚る。å„メソッドã¯ã‚¨ãƒ©ãƒ¼æ™‚ã«ã‚¯ãƒ©ã‚¹ `DBMException' ã®ã‚¤ãƒ³ã‚¹ã‚¿ãƒ³ã‚¹ã‚’投ã’る。四ã¤ã®APIã‹ã‚‰é©åˆ‡ãªã‚‚ã®ã‚’é¸æŠžã™ã‚‹éš›ã«ã¯ã€å®Ÿè¡ŒåŠ¹çŽ‡ã‚’é‡è¦–ã™ã‚‹ãªã‚‰ `Depot' ã‚’ã€ã‚¹ã‚±ãƒ¼ãƒ©ãƒ“リティをé‡è¦–ã™ã‚‹ãªã‚‰ `Curia' ã‚’ã€é †åºã«åŸºã¥ãå‚ç…§ãŒå¿…è¦ãªã‚‰ `Villa' ã‚’ã€ã‚¨ãƒ¬ã‚¬ãƒ³ã‚¹ã¨ä¿å®ˆæ€§ã‚’é‡è¦–ã™ã‚‹ãªã‚‰ `ADBM' ã‚’é¸ã¶ã¹ãã§ã‚ã‚ã†ã€‚データベースファイルã¯å„APIã®é–“ã§äº’æ›æ€§ãŒãªã„。

å„クラスã¯ãƒ‘ッケージ `qdbm' ã«å«ã¾ã‚Œã€ã‚¢ãƒ—リケーションã®ã‚½ãƒ¼ã‚¹ãƒ•ァイルã§ãれをインãƒãƒ¼ãƒˆã™ã‚‹ã“ã¨ãŒã§ãる。

Cã®APIã¯ã€ã‚¹ãƒ¬ãƒƒãƒ‰é–“ã§ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’共有ã—ãªã„é™ã‚Šã¯ã‚¹ãƒ¬ãƒƒãƒ‰ã‚»ãƒ¼ãƒ•ã§ã‚る。Javaã®APIã§ã¯ã€è¤‡æ•°ã®ã‚¹ãƒ¬ãƒƒãƒ‰ãŒåŒã˜ãƒãƒ³ãƒ‰ãƒ«ã«ã‚¢ã‚¯ã‚»ã‚¹ã—ã¦ã‚‚スレッドセーフã§ã‚る。

`put' ã§æ—¢å­˜ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã®ä¸Šæ›¸ããŒã‚­ãƒ£ãƒ³ã‚»ãƒ«ã•れãŸéš›ã‚„ `get' ã§å­˜åœ¨ã—ãªã„ãƒ¬ã‚³ãƒ¼ãƒ‰ãŒæ¤œç´¢ã•れãŸéš›ã«ã¯ä¾‹å¤–ã«ã‚ˆã£ã¦æ“作ã®å¤±æ•—ãŒé€šçŸ¥ã•れるãŒã€ãれãŒé¬±é™¶ã—ã„å ´åˆã¯ `silent' フラグを真ã«ã™ã‚‹ã¨ã‚ˆã„。ãã®å ´åˆã¯å¤±æ•—ãŒæˆ»ã‚Šå€¤ã«ã‚ˆã£ã¦é€šçŸ¥ã•れる。

APIã®è©³ç´°ã«é–¢ã—ã¦ã¯ã€ã‚µãƒ–ディレクトリ `japidoc' ã®æ–‡æ›¸ã‚’å‚ç…§ã™ã‚‹ã“ã¨ã€‚


インストール

準備

JDKã®1.2以é™ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ãŒã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•れã€ç’°å¢ƒå¤‰æ•° `JAVA_HOME' ãŒé©åˆ‡ã«è¨­å®šã•れã€QDBM㌠`/usr/local' 以下ã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•れã¦ã„ã‚‹ã“ã¨ãŒå¿…è¦ã§ã‚る。

インストール作業ã¯ã€ã‚µãƒ–ディレクトリ `java' をカレントディレクトリã«ã—ã¦è¡Œã†ã€‚

cd java

æ™®é€šã®æ‰‹é †

ビルド環境を設定ã™ã‚‹ã€‚Javaã®ã‚³ãƒ³ãƒ‘イルã«GCCを用ã„ã‚‹å ´åˆã€`--with-gcj' オプションを付ã‘る。

./configure

プログラムをビルドã™ã‚‹ã€‚

make

プログラムã®è‡ªå·±è¨ºæ–­ãƒ†ã‚¹ãƒˆã‚’行ã†ã€‚

make check

プログラムをインストールã™ã‚‹ã€‚作業㯠`root' ユーザã§è¡Œã†ã€‚

make install

一連ã®ä½œæ¥­ãŒçµ‚ã‚‹ã¨ã€ãƒã‚¤ãƒ†ã‚£ãƒ–ライブラリ `libjqdbm.so' ç­‰ã¨JARファイル `qdbm.jar' ㌠`/usr/local/lib' ã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•れる。

アンインストールã™ã‚‹ã«ã¯ã€`./configure' ã‚’ã—ãŸå¾Œã®çŠ¶æ…‹ã§ä»¥ä¸‹ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹ã€‚作業㯠`root' ユーザã§è¡Œã†ã€‚

make uninstall

Windowsã®å ´åˆ

Windows(Cygwin)ã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã™ã‚‹å ´åˆã€ä»¥ä¸‹ã®æ‰‹é †ã«å¾“ã†ã€‚

ビルド環境を設定ã™ã‚‹ã€‚

./configure

プログラムをビルドã™ã‚‹ã€‚

make win

プログラムã®è‡ªå·±è¨ºæ–­ãƒ†ã‚¹ãƒˆã‚’行ã†ã€‚

make check-win

プログラムをインストールã™ã‚‹ã€‚ãªãŠã€ã‚¢ãƒ³ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã™ã‚‹å ´åˆã¯ `make uninstall-win' ã¨ã™ã‚‹ã€‚

make install-win

Windowsã§ã¯ã€ã‚¤ãƒ³ãƒãƒ¼ãƒˆãƒ©ã‚¤ãƒ–ラリ `libjqdbm.dll.a' ãŒç”Ÿæˆã•れã€ã•らã«ãƒ€ã‚¤ãƒŠãƒŸãƒƒã‚¯ãƒªãƒ³ã‚¯ãƒ©ã‚¤ãƒ–ラリ `jqdbm.dll' ãŒç”Ÿæˆã•れる。`jqdbm.dll' 㯠`/usr/local/bin' ã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•れる。

Cygwin環境ã§MinGWを用ã„ã¦ãƒ“ルドã™ã‚‹ã«ã¯ã€`make win' ã®ä»£ã‚り㫠`make mingw' を用ã„る。Cygwinã®UNIXエミュレーション層を用ã„ã‚‹å ´åˆã€ç”Ÿæˆã•れるプログラム㯠`cygwin1.dll' ã«ä¾å­˜ã—ãŸã‚‚ã®ã«ãªã‚‹ã€‚MinGWã«ã‚ˆã£ã¦Win32ã®ãƒã‚¤ãƒ†ã‚£ãƒ–DLLã¨ãƒªãƒ³ã‚¯ã•ã›ã‚Œã°ã“ã®å•題を回é¿ã§ãる。

Mac OS Xã®å ´åˆ

Mac OS X(Darwin)ã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã™ã‚‹å ´åˆã€ä»¥ä¸‹ã®æ‰‹é †ã«å¾“ã†ã€‚

ビルド環境を設定ã™ã‚‹ã€‚

./configure

プログラムをビルドã™ã‚‹ã€‚

make mac

プログラムã®è‡ªå·±è¨ºæ–­ãƒ†ã‚¹ãƒˆã‚’行ã†ã€‚

make check-mac

プログラムをインストールã™ã‚‹ã€‚ãªãŠã€ã‚¢ãƒ³ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã™ã‚‹å ´åˆã¯ `make uninstall-mac' ã¨ã™ã‚‹ã€‚

make install-mac

Mac OS Xã§ã¯ã€`libjqdbm.so' ç­‰ã®ä»£ã‚り㫠`libjqdbm.dylib' ã‚„ `libjqdbm.jnilib' ç­‰ãŒç”Ÿæˆã•れる。

HP-UXã®å ´åˆ

HP-UXã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã™ã‚‹å ´åˆã€ä»¥ä¸‹ã®æ‰‹é †ã«å¾“ã†ã€‚

ビルド環境を設定ã™ã‚‹ã€‚

./configure

プログラムをビルドã™ã‚‹ã€‚

make hpux

プログラムã®è‡ªå·±è¨ºæ–­ãƒ†ã‚¹ãƒˆã‚’行ã†ã€‚

make check-hpux

プログラムをインストールã™ã‚‹ã€‚ãªãŠã€ã‚¢ãƒ³ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã™ã‚‹å ´åˆã¯ `make uninstall-hpux' ã¨ã™ã‚‹ã€‚

make install-hpux

HP-UXã§ã¯ã€`libjqdbm.so' ç­‰ã®ä»£ã‚り㫠`libjqdbm.sl' ãŒç”Ÿæˆã•れる。


環境設定

QDBMを利用ã—ãŸJavaプログラムをビルドã—ãŸã‚Šã€ãれを実行ã—ãŸã‚Šã™ã‚‹ã«ã¯ã€ç’°å¢ƒå¤‰æ•°ã‚’設定ã—ã¦ãŠãå¿…è¦ãŒã‚る。

クラスパスを設定ã™ã‚‹ã€‚環境変数 `CLASSPATH' ã®å€¤ãŒJARファイルã®ãƒ•ルパスをå«ã‚€ã‚ˆã†ã«ã™ã‚‹ã€‚

CLASSPATH=$CLASSPATH:/usr/local/lib/qdbm.jar
export CLASSPATH

ライブラリパスを設定ã™ã‚‹ã€‚環境変数 `LD_LIBRARY_PATH' ã®å€¤ãŒãƒ©ã‚¤ãƒ–ラリã®ã‚るディレクトリをå«ã‚€ã‚ˆã†ã«ã™ã‚‹ã€‚ãªãŠã€Windowsã§ã¯ã“ã®è¨­å®šã¯ä¸è¦ã§ã‚りã€Mac OS Xã§ã¯ç’°å¢ƒå¤‰æ•° `DYLD_LIBRARY_PATH' を用ã„ã€HP-UXã§ã¯ç’°å¢ƒå¤‰æ•° `SHLIB_PATH' を用ã„る。

LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib
export LD_LIBRARY_PATH

サンプルコード

åå‰ã¨å¯¾å¿œã•ã›ã¦é›»è©±ç•ªå·ã‚’æ ¼ç´ã—ã€ãれを検索ã™ã‚‹ã‚¢ãƒ—リケーションã®ã‚µãƒ³ãƒ—ルコードを以下ã«ç¤ºã™ã€‚

import qdbm.*;

public class Sample {

  static final String NAME = "mikio";
  static final String NUMBER = "000-1234-5678";
  static final String DBNAME = "book";

  public static void main(String[] args){
    Depot depot = null;
    try {

      // データベースを開ã
      depot = new Depot(DBNAME, Depot.OWRITER | Depot.OCREAT, -1);

      // レコードを格ç´ã™ã‚‹
      depot.put(NAME.getBytes(), NUMBER.getBytes());

      // レコードをå–å¾—ã™ã‚‹
      byte[] res = depot.get(NAME.getBytes());
      System.out.println("Name: " + NAME);
      System.out.println("Number: " + new String(res));

    } catch(DepotException e){
      e.printStackTrace();
    } finally {

      // データベースを閉ã˜ã‚‹
      if(depot != null){
        try {
          depot.close();
        } catch(DepotException e){
          e.printStackTrace();
        }
      }

    }
  }

}

上記ã®ä¾‹ã‚’ `ADBM' クラスを用ã„ã¦æ›¸ãç›´ã—ãŸä¾‹ã‚’以下ã«ç¤ºã™ã€‚

import qdbm.*;

public class Sample {

  static final String NAME = "mikio";
  static final String NUMBER = "000-1234-5678";
  static final String DBNAME = "book";

  public static void main(String[] args){
    ADBM dbm = null;
    try {

      // データベースを開ã
      dbm = new Depot(DBNAME, Depot.OWRITER | Depot.OCREAT, -1);

      // レコードを格ç´ã™ã‚‹
      dbm.store(NAME.getBytes(), NUMBER.getBytes(), true);

      // レコードをå–å¾—ã™ã‚‹
      byte[] res = dbm.fetch(NAME.getBytes());
      System.out.println("Name: " + NAME);
      System.out.println("Number: " + new String(res));

    } catch(DBMException e){
      e.printStackTrace();
    } finally {

      // データベースを閉ã˜ã‚‹
      if(dbm != null){
        try {
          dbm.close();
        } catch(DBMException e){
          e.printStackTrace();
        }
      }

    }
  }

}

`Villa' クラスを用ã„ã¦æ–‡å­—列ã®å‰æ–¹ä¸€è‡´æ¤œç´¢ã‚’行ã†ä¾‹ã‚’以下ã«ç¤ºã™ã€‚

import qdbm.*;

public class Sample {

  static final String DBNAME = "words";
  static final String PREFIX = "apple";

  public static void main(String[] args){
    Villa villa = null;
    try {

      // データベースを開ã
      villa = new Villa(DBNAME, Villa.OWRITER | Villa.OCREAT, Villa.CMPOBJ);

      // レコードを格ç´ã™ã‚‹
      villa.putobj("applet", "little application", Villa.DDUP);
      villa.putobj("aurora", "polar wonderwork", Villa.DDUP);
      villa.putobj("apple", "delicious fruit", Villa.DDUP);
      villa.putobj("amigo", "good friend", Villa.DDUP);
      villa.putobj("apple", "big city", Villa.DDUP);

      try {

        // カーソルを候補ã®å…ˆé ­ã«ç½®ã
        villa.curjumpobj(PREFIX, Villa.JFORWARD);

        // カーソルを走査ã™ã‚‹
        for(;;){
          String key = (String)villa.curkeyobj();
          if(!key.startsWith(PREFIX)) break;
          String val = (String)villa.curvalobj();
          System.out.println(key + ": " + val);
          villa.curnext();
        }

      } catch(VillaException e){
        if(e.ecode != Villa.ENOITEM) throw e;
      }
    } catch(VillaException e){
      e.printStackTrace();
    } finally {

      // データベースを閉ã˜ã‚‹
      if(villa != null){
        try {
          villa.close();
        } catch(VillaException e){
          e.printStackTrace();
        }
      }

    }
  }

}

Java用APIを利用ã—ãŸãƒ—ログラムをビルドã™ã‚‹ã«ã¯ã€ã‚¯ãƒ©ã‚¹ãƒ‘スをé©åˆ‡ã«è¨­å®šã—ãŸä¸Šã§ã€`javac' を実行ã™ã‚‹ã€‚例ãˆã°ã€`Sample.java' ã‹ã‚‰ `Sample.class' を作るã«ã¯ã€ä»¥ä¸‹ã®ã‚ˆã†ã«ãƒ“ルドを行ã†ã€‚

javac Sample.java

ãƒã‚°

ã²ã¨ã¤ã®ãƒ—ロセスã§è¤‡æ•°ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ã‚¡ã‚¤ãƒ«ã‚’åŒæ™‚ã«åˆ©ç”¨ã™ã‚‹ã“ã¨ã¯å¯èƒ½ã§ã‚ã‚‹ãŒã€åŒã˜ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルã®è¤‡æ•°ã®ãƒãƒ³ãƒ‰ãƒ«ã‚’利用ã—ã¦ã¯ãªã‚‰ãªã„。ã²ã¨ã¤ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’複数ã®ã‚¹ãƒ¬ãƒƒãƒ‰ã§åˆ©ç”¨ã™ã‚‹å ´åˆã«ã¯ã€ãƒ¡ã‚¤ãƒ³ã‚¹ãƒ¬ãƒƒãƒ‰ã§ç”Ÿæˆã—ãŸãƒãƒ³ãƒ‰ãƒ«ã‚’ä»–ã®ã‚¹ãƒ¬ãƒƒãƒ‰ã«æ¸¡ã›ã°ã‚ˆã„。

オブジェクトを直列化ã—ã¦ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«æ ¼ç´ã™ã‚‹æ‰‹æ³•ã¯ä¾¿åˆ©ã§ã‚ã‚‹ãŒã€ã‚ªãƒ–ジェクトã®ç›´åˆ—åŒ–ã¯æ™‚é–“çš„ãŠã‚ˆã³ç©ºé–“çš„ã«åŠ¹çŽ‡ãŒã‚ˆããªã„。明示的ã«ãƒã‚¤ãƒˆé…列ã«å¤‰æ›ã§ãã‚‹ãªã‚‰ã°ã€ãªã‚‹ã¹ããƒã‚¤ãƒˆé…列を格ç´ã—ãŸæ–¹ãŒã‚ˆã„。ã¾ãŸã€ãƒãƒƒã‚·ãƒ¥ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã®ã‚­ãƒ¼ã®æ¯”較ã¯ã‚ªãƒ–ジェクトã«å¯¾ã—ã¦ã‚‚直列化ã—ãŸçŠ¶æ…‹ã§è¡Œã‚れる。ã™ãªã‚ã¡ã€äºŒã¤ã®ã‚ªãƒ–ジェクトãŒç›´åˆ—化ã—ãŸçŠ¶æ…‹ã§å®Œå…¨ã«ä¸€è‡´ã—ãªã„å ´åˆã¯ã€ãŸã¨ãˆ `equals' ã®å€¤ãŒçœŸã§ã‚ã£ã¦ã‚‚ã€ä¸€è‡´ã—ãŸã‚­ãƒ¼ã¨ã¯ã¿ãªã•れãªã„。B+木データベースã§ã¯æ¯”較関数をé©åˆ‡ã«æŒ‡å®šã§ãã‚‹ã®ã§ã“ã®å•題ã¯ãªã„。


qdbm-1.8.78/java/VillaException.java0000644000175000017500000000347310355663556016303 0ustar mikiomikio/************************************************************************************************* * Exception container of Villa * Copyright (C) 2000-2006 Mikio Hirabayashi * This file is part of QDBM, Quick Database Manager. * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU * Lesser General Public License as published by the Free Software Foundation; either version * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * You should have received a copy of the GNU Lesser General Public License along with QDBM; if * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. *************************************************************************************************/ package qdbm; /** * Exception container of Villa. */ public class VillaException extends DBMException { //---------------------------------------------------------------- // instance fields //---------------------------------------------------------------- /** error code */ public final int ecode; //---------------------------------------------------------------- // public or protected methods //---------------------------------------------------------------- /** * Set the error code with `Villa.EMISC'. */ public VillaException(){ this(Villa.EMISC); } /** * Set the error code. * @param ecode an error code. */ public VillaException(int ecode){ super(Villa.errmsg(ecode)); this.ecode = ecode; } } /* END OF FILE */ qdbm-1.8.78/java/configure.in0000644000175000017500000001366310573423653015017 0ustar mikiomikio# Source of configuration for Java interface of QDBM #================================================================ # Generic Settings #================================================================ # Targets AC_INIT(qdbm-java, 1.0.0) # Export variables LIBVER=1 LIBREV=0 TARGETS="all" MYJAVAHOME="/usr/java" JVMPLATFORM="linux" JAVAC="javac" JAR="jar" JAVAH="javah" JAVADOC="javadoc" JAVARUN="java" MYDEFS="" MYOPTS="" LD="ld" # Building paths pathtmp="$PATH" PATH="$HOME/bin:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin" PATH="$PATH:/usr/ccs/bin:/usr/ucb:/usr/xpg4/bin:/usr/xpg6/bin:$pathtmp" LIBRARY_PATH="$HOME/lib:/usr/local/lib:$LIBRARY_PATH" LD_LIBRARY_PATH="$HOME/lib:/usr/local/lib:$LD_LIBRARY_PATH" CPATH="$HOME/include:/usr/local/include:$CPATH" export PATH LIBRARY_PATH LD_LIBRARY_PATH CPATH #================================================================ # Options #================================================================ # Debug mode AC_ARG_ENABLE(debug, AC_HELP_STRING([--enable-debug], [build for debugging])) if test "$enable_debug" = "yes" then TARGETS="debug" fi # Developping mode AC_ARG_ENABLE(devel, AC_HELP_STRING([--enable-devel], [build for development])) if test "$enable_devel" = "yes" then TARGETS="devel" fi # Enable gcj AC_ARG_WITH(gcj, AC_HELP_STRING([--with-gcj], [build with gcj, gcc for Java])) #================================================================ # Checking Commands to Build with #================================================================ # Home directory of Java printf 'checking MYJAVAHOME... ' if test -d "$JAVA_HOME" then MYJAVAHOME="$JAVA_HOME" fi printf '%s\n' "$MYJAVAHOME" # Platform of Java printf 'checking JVMPLATFORM... ' if uname | grep Darwin > /dev/null then JVMPLATFORM="mac" else for file in `\ls $MYJAVAHOME/include` do if test -d "$MYJAVAHOME/include/$file" then JVMPLATFORM="$file" fi done fi printf '%s\n' "$JVMPLATFORM" # Java compiler printf 'checking JAVAC... ' JAVAC="$MYJAVAHOME/bin/javac" if uname | grep Darwin > /dev/null then if test -x "$MYJAVAHOME/Commands/javac" then JAVAC="$MYJAVAHOME/Commands/javac" else JAVAC="$MYJAVAHOME/bin/javac" fi fi if test "$with_gcj" = "yes" then JAVAC="gcj -C -Wall" printf 'gcj -C -Wall\n' elif test -x "$JAVAC" then printf '%s\n' "$JAVAC" else printf 'no\n' printf '#================================================================\n' 1>&2 printf '# WARNING: %s is not found.\n' "$JAVAC" 1>&2 printf '#================================================================\n' 1>&2 fi # Other building tools if test "$with_gcj" = "yes" then JAR="jar" JAVAH="gcjh" JAVADOC="false" JAVARUN="gij" elif uname | grep Darwin > /dev/null then if test -x "$MYJAVAHOME/Commands/java" then JAR="$MYJAVAHOME/Commands/jar" JAVAH="$MYJAVAHOME/Commands/javah" JAVADOC="$MYJAVAHOME/Commands/javadoc" JAVARUN="$MYJAVAHOME/Commands/java" else JAR="$MYJAVAHOME/bin/jar" JAVAH="$MYJAVAHOME/bin/javah" JAVADOC="$MYJAVAHOME/bin/javadoc" JAVARUN="$MYJAVAHOME/bin/java" fi else JAR="$MYJAVAHOME/bin/jar" JAVAH="$MYJAVAHOME/bin/javah" JAVADOC="$MYJAVAHOME/bin/javadoc" JAVARUN="$MYJAVAHOME/bin/java" fi # C compiler AC_PROG_CC if test "$GCC" != "yes" then printf '#================================================================\n' 1>&2 printf '# WARNING: GCC is required to build this package.\n' 1>&2 printf '#================================================================\n' 1>&2 fi if uname | egrep -i 'SunOS' > /dev/null 2>&1 then MYOPTS="-O1" fi if uname | egrep -i 'BSD' > /dev/null 2>&1 then MYOPTS="-O1" fi if gcc --version | egrep -i '^2\.(8|9)' > /dev/null 2>&1 then MYOPTS="-O1" fi # Linker printf 'checking for ld... ' if which ld | grep '/ld$' > /dev/null 2>&1 then LD=`which ld` printf '%s\n' "$LD" else printf 'no\n' printf '#================================================================\n' 1>&2 printf '# WARNING: ld is not found in PATH.\n' 1>&2 printf '#================================================================\n' 1>&2 fi #================================================================ # Checking Libraries #================================================================ # Underlying libraries AC_CHECK_LIB(c, main) AC_CHECK_LIB(pthread, main) AC_CHECK_LIB(z, main) AC_CHECK_LIB(lzo2, main) AC_CHECK_LIB(bz2, main) AC_CHECK_LIB(iconv, main) # Fundamental QDBM libraries AC_CHECK_LIB(qdbm, main, true, printf 'checking whether /usr/local/lib/libqdbm.* is... ' if ls /usr/local/lib/libqdbm.* > /dev/null 2>&1 then printf 'yes\n' else printf 'no\n' printf '#================================================================\n' 1>&2 printf '# WARNING: Install QDBM libraries before installation.\n' 1>&2 printf '#================================================================\n' 1>&2 fi ) # For old BSDs if uname -a | grep BSD > /dev/null && test -f /usr/lib/libc_r.a && test ! -f /usr/lib/libpthread.a then LIBS=`printf '%s' "$LIBS" | sed 's/-lc/-lc_r/g'` fi # Duplication of QDBM for Java AC_CHECK_LIB(jqdbm, main, printf '#================================================================\n' 1>&2 printf '# WARNING: An old library was detected.\n' 1>&2 printf '#================================================================\n' 1>&2 ) #================================================================ # Generic Settings #================================================================ # Data types if uname | grep '^SunOS' > /dev/null then MYDEFS='-Dint64_t=long\ long' elif uname | grep '^CYGWIN' > /dev/null then MYDEFS='-D__int64=long\ long' fi # Export variables AC_SUBST(LIBVER) AC_SUBST(LIBREV) AC_SUBST(TARGETS) AC_SUBST(MYJAVAHOME) AC_SUBST(JVMPLATFORM) AC_SUBST(JAVAC) AC_SUBST(JAR) AC_SUBST(JAVAH) AC_SUBST(JAVADOC) AC_SUBST(JAVARUN) AC_SUBST(MYDEFS) AC_SUBST(MYOPTS) AC_SUBST(LD) AC_SUBST(CPPFLAGS) AC_SUBST(LDFLAGS) # Targets AC_OUTPUT(Makefile) # END OF FILE qdbm-1.8.78/java/VillaTester.java0000644000175000017500000002215710441505617015600 0ustar mikiomikio/************************************************************************************************* * Test cases for Villa for Java * Copyright (C) 2000-2006 Mikio Hirabayashi * This file is part of QDBM, Quick Database Manager. * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU * Lesser General Public License as published by the Free Software Foundation; either version * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * You should have received a copy of the GNU Lesser General Public License along with QDBM; if * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. *************************************************************************************************/ package qdbm; /** * Test case for Villa. */ class VillaTester extends Thread { //---------------------------------------------------------------- // constants //---------------------------------------------------------------- private static final int LOOPNUM = 10000; private static final int THREADNUM = 10; private static final java.util.Random RND = new java.util.Random(); //---------------------------------------------------------------- // instance fields //---------------------------------------------------------------- private Villa myvilla; private int myid; private boolean myprinter; private VillaException myve; //---------------------------------------------------------------- // public or protected methods //---------------------------------------------------------------- /** * Main routine. * @param args specifies a name of a database file with the first element. */ public static void main(String[] args) throws Exception { if(args.length != 1){ System.err.println("usege: java qdbm.VillaTester name"); return; } if(!dowrite(args[0], false)) System.exit(1); if(!doread(args[0])) System.exit(1); if(!domulti(args[0], false)) System.exit(1); if(!dowrite(args[0], true)) System.exit(1); if(!doread(args[0])) System.exit(1); if(!domulti(args[0], true)) System.exit(1); System.out.println("all ok"); System.out.println(""); System.exit(0); } /** * Perform writing test. * @param name specifies a name of a database. * @param zc specifies whether to compress leaves in the database. * @return whether the test is success or not. */ public static boolean dowrite(String name, boolean zc){ System.out.println(""); System.out.println(" name=" + name); System.out.println(""); Villa villa = null; boolean err = false; try { // open a database System.out.print("Creating ... "); int omode = Villa.OWRITER | Villa.OCREAT | Villa.OTRUNC; if(zc) omode |= Villa.OZCOMP; villa = new Villa(name, omode, Villa.CMPLEX); System.out.println("ok"); // loop for storing System.out.println("Writing"); for(int i = 1; i <= LOOPNUM; i++){ byte[] buf = Util.numstr(i, 8, '0').getBytes(); // store a record into the database villa.put(buf, buf, Villa.DOVER); // print progression if(i % (LOOPNUM / 250) == 0){ System.out.print('.'); System.out.flush(); if(i == LOOPNUM || i % (LOOPNUM / 10) == 0){ System.out.println(" (" + new String(buf) + ")"); System.out.flush(); } } } System.out.println("ok"); } catch(VillaException e){ err = true; // report an error System.err.println(e); } finally { try { // close the database System.out.print("Closing ... "); if(villa != null) villa.close(); System.out.println("ok"); } catch(VillaException e){} } System.out.println(""); return err ? false : true; } /** * Perform reading test. * @param name specifies a name of a database. * @return whether the test is success or not. */ public static boolean doread(String name){ System.out.println(""); System.out.println(" name=" + name); System.out.println(""); Villa villa = null; boolean err = false; try { // open a database System.out.print("Opening ... "); villa = new Villa(name); System.out.println("ok"); System.out.println("Reading"); // loop for retrieving for(int i = 1; i <= LOOPNUM; i++){ byte[] buf = Util.numstr(i, 8, '0').getBytes(); // retrieve a record from the database villa.get(buf); // print progression if(i % (LOOPNUM / 250) == 0){ System.out.print('.'); System.out.flush(); if(i == LOOPNUM || i % (LOOPNUM / 10) == 0){ System.out.println(" (" + new String(buf) + ")"); System.out.flush(); } } } System.out.println("ok"); } catch(VillaException e){ err = true; // report an error System.err.println(e); } finally { try { // close the database System.out.print("Closing ... "); if(villa != null) villa.close(); System.out.println("ok"); } catch(VillaException e){} } System.out.println(""); return err ? false : true; } /** * Perform multi thread test. * @param name specifies a name of a database. * @param zc specifies whether to compress leaves in the database. * @return whether the test is success or not. */ public static boolean domulti(String name, boolean zc){ System.out.println(""); System.out.println(" name=" + name); System.out.println(""); Villa villa = null; boolean err = false; try { // open a database System.out.print("Opening ... "); int omode = Villa.OWRITER | Villa.OCREAT | Villa.OTRUNC; if(zc) omode |= Villa.OZCOMP; villa = new Villa(name, omode, Villa.CMPLEX); System.out.println("ok"); // prepare threads VillaTester[] dts = new VillaTester[THREADNUM]; // roop for each threads System.out.println("Writing"); for(int i = 0; i < dts.length; i++){ dts[i] = new VillaTester(villa, i, i == dts.length / 2); dts[i].start(); } // join every threads for(int i = 0; i < dts.length; i++){ try { dts[i].join(); if(dts[i].myve != null){ err = true; System.err.println(dts[i].myve); } } catch(InterruptedException e){ i--; } } if(!err) System.out.println("ok"); System.out.flush(); // check every record System.out.print("Validation checking ... "); for(int i = 1; i <= LOOPNUM; i++){ byte[] buf = Util.numstr(i, 8, '0').getBytes(); byte[] val = villa.get(buf); if(val.length != 1 || villa.vsiz(buf) != 1){ err = true; System.err.println("size error: " + val.length); } int vnum = villa.vnum(buf); if(vnum != THREADNUM){ err = true; System.err.println("vnum error: " + vnum); } } if(!err) System.out.println("ok"); } catch(VillaException e){ err = true; System.err.println(e); } finally { try { // close the database System.out.print("Closing ... "); if(villa != null) villa.close(); System.out.println("ok"); } catch(VillaException e){} } System.out.println(""); return err ? false : true; } /** * Constructor for multi thread test. */ private VillaTester(Villa villa, int id, boolean printer){ myvilla = villa; myid = id; myprinter = printer; myve = null; } /** * Method for multi thread test. */ public void run(){ // roop for storing for(int i = 1; i <= LOOPNUM; i++){ // store a record into the database byte[] buf = Util.numstr(i, 8, '0').getBytes(); boolean tran = false; try { if(RND.nextInt(LOOPNUM / 7 + 1) == 0){ myvilla.tranbegin(); tran = true; } if(RND.nextInt(LOOPNUM / 20) == 0) yield(); myvilla.put(buf, (myid % 2 == 0 ? "=" : "*").getBytes(), RND.nextInt(3) == 0 ? Villa.DDUPR : Villa.DDUP); } catch(VillaException e){ try { if(tran) myvilla.tranabort(); } catch(VillaException ee){} myve = e; return; } try { if(tran) myvilla.trancommit(); } catch(VillaException e){ myve = e; return; } // print progression if(myprinter && i % (LOOPNUM / 250) == 0){ System.out.print('.'); System.out.flush(); if(i == LOOPNUM || i % (LOOPNUM / 10) == 0){ System.out.println(" (" + new String(buf) + ")"); System.out.flush(); // garbage collection test System.gc(); } } } } } /* END OF FILE */ qdbm-1.8.78/java/joverview0000644000175000017500000000353711426314474014446 0ustar mikiomikio Overview of QDBM

QDBM: Quick Database Manager.

QDBM is a library of routines for managing a database. The database is a simple data file containing records, each is a pair of a key and a value. Every key and value is serial bytes with variable length. Both binary data and character string can be used as a key and a value. There is neither concept of data tables nor data types. Records are organazed in hash table or B+ tree.

As for database of hash table, each key must be unique within a database, so it is impossible to store two or more records with a key overlaps. The following access methods are provided to the database: storing a record with a key and a value, deleting a record by a key, retrieving a record by a key. Moreover, traversal access to every key are provided, although the order is arbitrary. These access methods are similar to ones of DBM (or its followers, NDBM and GDBM) library defined in the UNIX standard. QDBM is an alternative for DBM because of its higher performance.

As for database of B+ tree, records whose keys are duplicated can be stored. Access methods of storing, deleting and retrieving are provided as with the database of hash table. Records are stored in order by a comparing function assigned by a user. It is possible to access each record with the cursor in ascending or descending order. According to this mechanism, forward matching search for strings and range search for integers are realized. Moreover, transaction is available in database of B+ tree.

This package is Java API for QDBM. This package contains native methods which are depends on native libraries of QDBM. Each class is packaged in `qdbm'.

Refer to `http://fallabs.com/qdbm/' for more information.

qdbm-1.8.78/java/qdbm_Curia.h0000644000175000017500000001607310432046225014711 0ustar mikiomikio/* DO NOT EDIT THIS FILE - it is machine generated */ #include /* Header for class qdbm_Curia */ #ifndef _Included_qdbm_Curia #define _Included_qdbm_Curia #ifdef __cplusplus extern "C" { #endif #undef qdbm_Curia_ENOERR #define qdbm_Curia_ENOERR 0L #undef qdbm_Curia_EFATAL #define qdbm_Curia_EFATAL 1L #undef qdbm_Curia_EMODE #define qdbm_Curia_EMODE 2L #undef qdbm_Curia_EBROKEN #define qdbm_Curia_EBROKEN 3L #undef qdbm_Curia_EKEEP #define qdbm_Curia_EKEEP 4L #undef qdbm_Curia_ENOITEM #define qdbm_Curia_ENOITEM 5L #undef qdbm_Curia_EALLOC #define qdbm_Curia_EALLOC 6L #undef qdbm_Curia_EMAP #define qdbm_Curia_EMAP 7L #undef qdbm_Curia_EOPEN #define qdbm_Curia_EOPEN 8L #undef qdbm_Curia_ECLOSE #define qdbm_Curia_ECLOSE 9L #undef qdbm_Curia_ETRUNC #define qdbm_Curia_ETRUNC 10L #undef qdbm_Curia_ESYNC #define qdbm_Curia_ESYNC 11L #undef qdbm_Curia_ESTAT #define qdbm_Curia_ESTAT 12L #undef qdbm_Curia_ESEEK #define qdbm_Curia_ESEEK 13L #undef qdbm_Curia_EREAD #define qdbm_Curia_EREAD 14L #undef qdbm_Curia_EWRITE #define qdbm_Curia_EWRITE 15L #undef qdbm_Curia_ELOCK #define qdbm_Curia_ELOCK 16L #undef qdbm_Curia_EUNLINK #define qdbm_Curia_EUNLINK 17L #undef qdbm_Curia_EMKDIR #define qdbm_Curia_EMKDIR 18L #undef qdbm_Curia_ERMDIR #define qdbm_Curia_ERMDIR 19L #undef qdbm_Curia_EMISC #define qdbm_Curia_EMISC 20L #undef qdbm_Curia_OREADER #define qdbm_Curia_OREADER 1L #undef qdbm_Curia_OWRITER #define qdbm_Curia_OWRITER 2L #undef qdbm_Curia_OCREAT #define qdbm_Curia_OCREAT 4L #undef qdbm_Curia_OTRUNC #define qdbm_Curia_OTRUNC 8L #undef qdbm_Curia_ONOLCK #define qdbm_Curia_ONOLCK 16L #undef qdbm_Curia_OLCKNB #define qdbm_Curia_OLCKNB 32L #undef qdbm_Curia_OSPARSE #define qdbm_Curia_OSPARSE 64L #undef qdbm_Curia_DOVER #define qdbm_Curia_DOVER 0L #undef qdbm_Curia_DKEEP #define qdbm_Curia_DKEEP 1L #undef qdbm_Curia_DCAT #define qdbm_Curia_DCAT 2L /* Inaccessible static: class_00024qdbm_00024ADBM */ /* * Class: qdbm_Curia * Method: crinit * Signature: ()V */ JNIEXPORT void JNICALL Java_qdbm_Curia_crinit (JNIEnv *, jclass); /* * Class: qdbm_Curia * Method: crversion * Signature: ()Ljava/lang/String; */ JNIEXPORT jstring JNICALL Java_qdbm_Curia_crversion (JNIEnv *, jclass); /* * Class: qdbm_Curia * Method: crecode * Signature: ()I */ JNIEXPORT jint JNICALL Java_qdbm_Curia_crecode (JNIEnv *, jclass); /* * Class: qdbm_Curia * Method: crerrmsg * Signature: (I)Ljava/lang/String; */ JNIEXPORT jstring JNICALL Java_qdbm_Curia_crerrmsg (JNIEnv *, jclass, jint); /* * Class: qdbm_Curia * Method: cropen * Signature: (Ljava/lang/String;III)I */ JNIEXPORT jint JNICALL Java_qdbm_Curia_cropen (JNIEnv *, jclass, jstring, jint, jint, jint); /* * Class: qdbm_Curia * Method: crclose * Signature: (I)I */ JNIEXPORT jint JNICALL Java_qdbm_Curia_crclose (JNIEnv *, jclass, jint); /* * Class: qdbm_Curia * Method: crput * Signature: (I[BI[BII)I */ JNIEXPORT jint JNICALL Java_qdbm_Curia_crput (JNIEnv *, jclass, jint, jbyteArray, jint, jbyteArray, jint, jint); /* * Class: qdbm_Curia * Method: crout * Signature: (I[BI)I */ JNIEXPORT jint JNICALL Java_qdbm_Curia_crout (JNIEnv *, jclass, jint, jbyteArray, jint); /* * Class: qdbm_Curia * Method: crget * Signature: (I[BIII)[B */ JNIEXPORT jbyteArray JNICALL Java_qdbm_Curia_crget (JNIEnv *, jclass, jint, jbyteArray, jint, jint, jint); /* * Class: qdbm_Curia * Method: crvsiz * Signature: (I[BI)I */ JNIEXPORT jint JNICALL Java_qdbm_Curia_crvsiz (JNIEnv *, jclass, jint, jbyteArray, jint); /* * Class: qdbm_Curia * Method: criterinit * Signature: (I)I */ JNIEXPORT jint JNICALL Java_qdbm_Curia_criterinit (JNIEnv *, jclass, jint); /* * Class: qdbm_Curia * Method: criternext * Signature: (I)[B */ JNIEXPORT jbyteArray JNICALL Java_qdbm_Curia_criternext (JNIEnv *, jclass, jint); /* * Class: qdbm_Curia * Method: crsetalign * Signature: (II)I */ JNIEXPORT jint JNICALL Java_qdbm_Curia_crsetalign (JNIEnv *, jclass, jint, jint); /* * Class: qdbm_Curia * Method: crsetfbpsiz * Signature: (II)I */ JNIEXPORT jint JNICALL Java_qdbm_Curia_crsetfbpsiz (JNIEnv *, jclass, jint, jint); /* * Class: qdbm_Curia * Method: crsync * Signature: (I)I */ JNIEXPORT jint JNICALL Java_qdbm_Curia_crsync (JNIEnv *, jclass, jint); /* * Class: qdbm_Curia * Method: croptimize * Signature: (II)I */ JNIEXPORT jint JNICALL Java_qdbm_Curia_croptimize (JNIEnv *, jclass, jint, jint); /* * Class: qdbm_Curia * Method: crname * Signature: (I)Ljava/lang/String; */ JNIEXPORT jstring JNICALL Java_qdbm_Curia_crname (JNIEnv *, jclass, jint); /* * Class: qdbm_Curia * Method: crfsizd * Signature: (I)D */ JNIEXPORT jdouble JNICALL Java_qdbm_Curia_crfsizd (JNIEnv *, jclass, jint); /* * Class: qdbm_Curia * Method: crbnum * Signature: (I)I */ JNIEXPORT jint JNICALL Java_qdbm_Curia_crbnum (JNIEnv *, jclass, jint); /* * Class: qdbm_Curia * Method: crbusenum * Signature: (I)I */ JNIEXPORT jint JNICALL Java_qdbm_Curia_crbusenum (JNIEnv *, jclass, jint); /* * Class: qdbm_Curia * Method: crrnum * Signature: (I)I */ JNIEXPORT jint JNICALL Java_qdbm_Curia_crrnum (JNIEnv *, jclass, jint); /* * Class: qdbm_Curia * Method: crwritable * Signature: (I)I */ JNIEXPORT jint JNICALL Java_qdbm_Curia_crwritable (JNIEnv *, jclass, jint); /* * Class: qdbm_Curia * Method: crfatalerror * Signature: (I)I */ JNIEXPORT jint JNICALL Java_qdbm_Curia_crfatalerror (JNIEnv *, jclass, jint); /* * Class: qdbm_Curia * Method: crinode * Signature: (I)I */ JNIEXPORT jint JNICALL Java_qdbm_Curia_crinode (JNIEnv *, jclass, jint); /* * Class: qdbm_Curia * Method: crmtime * Signature: (I)J */ JNIEXPORT jlong JNICALL Java_qdbm_Curia_crmtime (JNIEnv *, jclass, jint); /* * Class: qdbm_Curia * Method: crputlob * Signature: (I[BI[BII)I */ JNIEXPORT jint JNICALL Java_qdbm_Curia_crputlob (JNIEnv *, jclass, jint, jbyteArray, jint, jbyteArray, jint, jint); /* * Class: qdbm_Curia * Method: croutlob * Signature: (I[BI)I */ JNIEXPORT jint JNICALL Java_qdbm_Curia_croutlob (JNIEnv *, jclass, jint, jbyteArray, jint); /* * Class: qdbm_Curia * Method: crgetlob * Signature: (I[BIII)[B */ JNIEXPORT jbyteArray JNICALL Java_qdbm_Curia_crgetlob (JNIEnv *, jclass, jint, jbyteArray, jint, jint, jint); /* * Class: qdbm_Curia * Method: crvsizlob * Signature: (I[BI)I */ JNIEXPORT jint JNICALL Java_qdbm_Curia_crvsizlob (JNIEnv *, jclass, jint, jbyteArray, jint); /* * Class: qdbm_Curia * Method: crrnumlob * Signature: (I)I */ JNIEXPORT jint JNICALL Java_qdbm_Curia_crrnumlob (JNIEnv *, jclass, jint); /* * Class: qdbm_Curia * Method: crremove * Signature: (Ljava/lang/String;)I */ JNIEXPORT jint JNICALL Java_qdbm_Curia_crremove (JNIEnv *, jclass, jstring); /* * Class: qdbm_Curia * Method: crsnaffle * Signature: (Ljava/lang/String;[BI)[B */ JNIEXPORT jbyteArray JNICALL Java_qdbm_Curia_crsnaffle (JNIEnv *, jclass, jstring, jbyteArray, jint); #ifdef __cplusplus } #endif #endif qdbm-1.8.78/java/DepotException.java0000644000175000017500000000347310355663555016306 0ustar mikiomikio/************************************************************************************************* * Exception container of Depot * Copyright (C) 2000-2006 Mikio Hirabayashi * This file is part of QDBM, Quick Database Manager. * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU * Lesser General Public License as published by the Free Software Foundation; either version * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * You should have received a copy of the GNU Lesser General Public License along with QDBM; if * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. *************************************************************************************************/ package qdbm; /** * Exception container of Depot. */ public class DepotException extends DBMException { //---------------------------------------------------------------- // instance fields //---------------------------------------------------------------- /** error code */ public final int ecode; //---------------------------------------------------------------- // public or protected methods //---------------------------------------------------------------- /** * Set the error code with `Depot.EMISC'. */ public DepotException(){ this(Depot.EMISC); } /** * Set the error code. * @param ecode an error code. */ public DepotException(int ecode){ super(Depot.errmsg(ecode)); this.ecode = ecode; } } /* END OF FILE */ qdbm-1.8.78/java/Util.java0000644000175000017500000001752510355663556014275 0ustar mikiomikio/************************************************************************************************* * Class of utility methods * Copyright (C) 2000-2006 Mikio Hirabayashi * This file is part of QDBM, Quick Database Manager. * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU * Lesser General Public License as published by the Free Software Foundation; either version * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * You should have received a copy of the GNU Lesser General Public License along with QDBM; if * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. *************************************************************************************************/ package qdbm; import java.io.IOException; import java.io.Serializable; import java.io.InputStream; import java.io.OutputStream; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.FileInputStream; import java.io.FileOutputStream; /** * Class of utility methods. * This class depends on the native library `jqdbm'. */ public class Util { //---------------------------------------------------------------- // public static constants //---------------------------------------------------------------- /** size of a long integer */ private static final int LONGSIZE = 8; private static final int IOBUFSIZ = 8192; //---------------------------------------------------------------- // static initializer //---------------------------------------------------------------- static { try { System.loadLibrary("jqdbm"); } catch(UnsatisfiedLinkError e){ e.printStackTrace(); } } //---------------------------------------------------------------- // public static methods //---------------------------------------------------------------- /** * Serialize an object. * @param obj a serializable object. * @return a byte array of the serialized object or null if an error occurs. */ public static byte[] serialize(Object obj){ ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = null; try { oos = new ObjectOutputStream(baos); oos.writeObject(obj); oos.flush(); baos.flush(); return baos.toByteArray(); } catch(IOException e){ return null; } finally { try { if(oos != null) oos.close(); } catch(IOException e){} } } /** * Redintegrate a serialized object. * @param serial a byte array of the serialized object. * @return an original object or null if an error occurs. */ public static Object deserialize(byte[] serial){ ByteArrayInputStream bais = new ByteArrayInputStream(serial); ObjectInputStream ois = null; try { ois = new ObjectInputStream(bais); return ois.readObject(); } catch(IOException e){ return null; } catch(ClassNotFoundException e){ return null; } finally { try { if(ois != null) ois.close(); } catch(IOException e){} } } /** * Serialize a long integer. * @param num a long integer. * @return a byte array of the serialized long integer. */ public static byte[] serializeLong(long num){ byte[] serial = new byte[LONGSIZE]; for(int i = 0; i < LONGSIZE; i++){ serial[LONGSIZE-i-1] = (byte)(num & 0xff); num >>= 8; } return serial; } /** * Redintegrate a serialized long integer. * @param serial a byte array of a serialized long integer. * @return the long value. * @throws IllegalArgumentException thrown if the size of the array is invalid. */ public static long deserializeLong(byte[] serial) throws IllegalArgumentException { if(serial.length != LONGSIZE) throw new IllegalArgumentException(); long num = 0; for(int i = 0; i < LONGSIZE; i++){ num *= 256; num += serial[i] + ((serial[i] < 0) ? 256 : 0); } return num; } /** * Get a formatted decimal string made from a number. * @param num a number. * @param cols the number of columns. The result string may be longer than it. * @param padding a padding character to fulfil columns with. */ public static String numstr(int num, int cols, char padding){ StringBuffer sb = new StringBuffer(cols); boolean minus = false; if(num < 0){ num *= -1; cols--; minus = true; } int i = 0; while(num > 0){ sb.insert(0, num % 10); num /= 10; i++; } while(i < cols){ sb.insert(0, padding); i++; } if(minus) sb.insert(0, '-'); return sb.toString(); } /** * Read whole data of a file. * @param path the path of a file. * @return while data of a file on success, or null on failure. */ public static byte[] readFile(String path){ InputStream is = null; ByteArrayOutputStream baos = null; try { is = new FileInputStream(path); baos = new ByteArrayOutputStream(); byte[] buf = new byte[IOBUFSIZ]; int len; while((len = is.read(buf)) != -1){ baos.write(buf, 0, len); } } catch(IOException e){ return null; } finally { try { if(baos != null) baos.close(); } catch(IOException e){} try { if(is != null) is.close(); } catch(IOException e){} } return baos.toByteArray(); } /** * Write whole data to a file. * @param path the path of a file. * @param data data to write. * @return true if success, false on failure. */ public static boolean writeFile(String path, byte[] data){ OutputStream os = null; try { os = new FileOutputStream(path); os.write(data); } catch(IOException e){ return false; } finally { try { if(os != null) os.close(); } catch(IOException e){} } return true; } //---------------------------------------------------------------- // public static native methods //---------------------------------------------------------------- /** * Execute a shell command using the native function `system' defined in POSIX and ANSI C. * @param cmd a command line. * @return the return value of the function. It depends on the native system. */ public static synchronized native int system(String cmd); /** * Change current working directory using the native function `chdir' defined in POSIX. * @param path the path of a directory. * @return 0 on success, or -1 on failure. */ public static synchronized native int chdir(String path); /** * Get current working directory using the native function `getcwd' defined in POSIX. * @return the path of the current working directory or null on failure. */ public static synchronized native String getcwd(); /** * Get process identification using the native function `getpid' defined in POSIX. * @return the process ID of the current process. */ public static synchronized native int getpid(); /** * Get an environment variable using the native function `getenv' defined in POSIX and ANSI C. * @param name the name of an environment variable. * @return the value of the variable, or null if it does not exist. */ public static synchronized native String getenv(String name); //---------------------------------------------------------------- // private methods //---------------------------------------------------------------- /* Default constructor. * This should not be used. */ private Util() throws Exception { throw new Exception(); } } /* END OF FILE */ qdbm-1.8.78/java/DBMException.java0000644000175000017500000000302410355663556015626 0ustar mikiomikio/************************************************************************************************* * Exception container of ADBM * Copyright (C) 2000-2006 Mikio Hirabayashi * This file is part of QDBM, Quick Database Manager. * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU * Lesser General Public License as published by the Free Software Foundation; either version * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * You should have received a copy of the GNU Lesser General Public License along with QDBM; if * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. *************************************************************************************************/ package qdbm; /** * Exception container of ADBM. */ public class DBMException extends Exception { //---------------------------------------------------------------- // public or protected methods //---------------------------------------------------------------- /** * Nothing specified. */ public DBMException(){ super("database error"); } /** * Nothing specified. */ public DBMException(String message){ super(message); } } /* END OF FILE */ qdbm-1.8.78/java/DepotTester.java0000644000175000017500000002023310431670453015575 0ustar mikiomikio/************************************************************************************************* * Test cases for Depot for Java * Copyright (C) 2000-2006 Mikio Hirabayashi * This file is part of QDBM, Quick Database Manager. * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU * Lesser General Public License as published by the Free Software Foundation; either version * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * You should have received a copy of the GNU Lesser General Public License along with QDBM; if * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. *************************************************************************************************/ package qdbm; /** * Test case for Depot. */ class DepotTester extends Thread { //---------------------------------------------------------------- // constants //---------------------------------------------------------------- private static final int LOOPNUM = 10000; private static final int BUCKETNUM = 1000; private static final int THREADNUM = 10; private static final java.util.Random RND = new java.util.Random(); //---------------------------------------------------------------- // instance fields //---------------------------------------------------------------- private Depot mydepot; private int myid; private boolean myprinter; private DepotException myde; //---------------------------------------------------------------- // public or protected methods //---------------------------------------------------------------- /** * Main routine. * @param args specifies a name of a database file with the first element. */ public static void main(String[] args){ if(args.length != 1){ System.err.println("usege: java qdbm.DepotTester name"); return; } if(!dowrite(args[0])) System.exit(1); if(!doread(args[0])) System.exit(1); if(!domulti(args[0])) System.exit(1); System.out.println("all ok"); System.out.println(""); System.exit(0); } /** * Perform writing test. * @param name specifies a name of a database. * @return whether the test is success or not. */ public static boolean dowrite(String name){ System.out.println(""); System.out.println(" name=" + name); System.out.println(""); Depot depot = null; boolean err = false; try { // open a database System.out.print("Creating ... "); depot = new Depot(name, Depot.OWRITER | Depot.OCREAT | Depot.OTRUNC, BUCKETNUM); System.out.println("ok"); // loop for storing System.out.println("Writing"); for(int i = 1; i <= LOOPNUM; i++){ byte[] buf = Util.numstr(i, 8, '0').getBytes(); // store a record into the database depot.put(buf, buf, Depot.DOVER); // print progression if(i % (LOOPNUM / 250) == 0){ System.out.print('.'); System.out.flush(); if(i == LOOPNUM || i % (LOOPNUM / 10) == 0){ System.out.println(" (" + new String(buf) + ")"); System.out.flush(); } } } System.out.println("ok"); } catch(DepotException e){ err = true; // report an error System.err.println(e); } finally { try { // close the database System.out.print("Closing ... "); if(depot != null) depot.close(); System.out.println("ok"); } catch(DepotException e){} } System.out.println(""); return err ? false : true; } /** * Perform reading test. * @param name specifies a name of a database. * @return whether the test is success or not. */ public static boolean doread(String name){ System.out.println(""); System.out.println(" name=" + name); System.out.println(""); Depot depot = null; boolean err = false; try { // open a database System.out.print("Opening ... "); depot = new Depot(name); System.out.println("ok"); System.out.println("Reading"); // loop for retrieving for(int i = 1; i <= LOOPNUM; i++){ byte[] buf = Util.numstr(i, 8, '0').getBytes(); // retrieve a record from the database depot.get(buf, 0, -1); // print progression if(i % (LOOPNUM / 250) == 0){ System.out.print('.'); System.out.flush(); if(i == LOOPNUM || i % (LOOPNUM / 10) == 0){ System.out.println(" (" + new String(buf) + ")"); System.out.flush(); } } } System.out.println("ok"); } catch(DepotException e){ err = true; // report an error System.err.println(e); } finally { try { // close the database System.out.print("Closing ... "); if(depot != null) depot.close(); System.out.println("ok"); } catch(DepotException e){} } System.out.println(""); return err ? false : true; } /** * Perform multi thread test. * @param name specifies a name of a database. * @return whether the test is success or not. */ public static boolean domulti(String name){ System.out.println(""); System.out.println(" name=" + name); System.out.println(""); Depot depot = null; boolean err = false; try { // open a database System.out.print("Opening ... "); depot = new Depot(name, Depot.OWRITER | Depot.OCREAT | Depot.OTRUNC, BUCKETNUM); System.out.println("ok"); // prepare threads DepotTester[] dts = new DepotTester[THREADNUM]; // roop for each threads System.out.println("Writing"); for(int i = 0; i < dts.length; i++){ dts[i] = new DepotTester(depot, i, i == dts.length / 2); dts[i].start(); } // join every threads for(int i = 0; i < dts.length; i++){ try { dts[i].join(); if(dts[i].myde != null){ err = true; System.err.println(dts[i].myde); } } catch(InterruptedException e){ i--; } } if(!err) System.out.println("ok"); System.out.flush(); // check every record System.out.print("Validation checking ... "); for(int i = 1; i <= LOOPNUM; i++){ byte[] buf = Util.numstr(i, 8, '0').getBytes(); byte[] val = depot.get(buf, 0, -1); if(val.length != THREADNUM){ err = true; System.err.println("size error: " + val.length); } } if(!err) System.out.println("ok"); } catch(DepotException e){ err = true; System.err.println(e); } finally { try { // close the database System.out.print("Closing ... "); if(depot != null) depot.close(); System.out.println("ok"); } catch(DepotException e){} } System.out.println(""); return err ? false : true; } /** * Constructor for multi thread test. */ private DepotTester(Depot depot, int id, boolean printer){ mydepot = depot; myid = id; myprinter = printer; myde = null; } /** * Method for multi thread test. */ public void run(){ // roop for storing for(int i = 1; i <= LOOPNUM; i++){ // store a record into the database byte[] buf = Util.numstr(i, 8, '0').getBytes(); try { if(RND.nextInt(LOOPNUM / 20) == 0) yield(); mydepot.put(buf, (myid % 2 == 0 ? "=" : "*").getBytes(), Depot.DCAT); } catch(DepotException e){ myde = e; return; } // print progression if(myprinter && i % (LOOPNUM / 250) == 0){ System.out.print('.'); System.out.flush(); if(i == LOOPNUM || i % (LOOPNUM / 10) == 0){ System.out.println(" (" + new String(buf) + ")"); System.out.flush(); // garbage collection test System.gc(); } } } } } /* END OF FILE */ qdbm-1.8.78/java/Depot.java0000644000175000017500000006020510505671462014414 0ustar mikiomikio/************************************************************************************************* * Java API of Depot, the basic API of QDBM * Copyright (C) 2000-2006 Mikio Hirabayashi * This file is part of QDBM, Quick Database Manager. * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU * Lesser General Public License as published by the Free Software Foundation; either version * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * You should have received a copy of the GNU Lesser General Public License along with QDBM; if * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. *************************************************************************************************/ package qdbm; /** * The Java API of Depot, the basic API of QDBM. * This class depends on the native library `jqdbm'. */ public class Depot implements ADBM { //---------------------------------------------------------------- // error codes //---------------------------------------------------------------- /** error code: no error */ public static final int ENOERR = 0; /** error code: with fatal error */ public static final int EFATAL = 1; /** error code: invalid mode */ public static final int EMODE = 2; /** error code: broken database file */ public static final int EBROKEN = 3; /** error code: existing record */ public static final int EKEEP = 4; /** error code: no item found */ public static final int ENOITEM = 5; /** error code: memory allocation error */ public static final int EALLOC = 6; /** error code: memory mapping error */ public static final int EMAP = 7; /** error code: open error */ public static final int EOPEN = 8; /** error code: close error */ public static final int ECLOSE = 9; /** error code: trunc error */ public static final int ETRUNC = 10; /** error code: sync error */ public static final int ESYNC = 11; /** error code: stat error */ public static final int ESTAT = 12; /** error code: seek error */ public static final int ESEEK = 13; /** error code: read error */ public static final int EREAD = 14; /** error code: write error */ public static final int EWRITE = 15; /** error code: lock error */ public static final int ELOCK = 16; /** error code: unlink error */ public static final int EUNLINK = 17; /** error code: mkdir error */ public static final int EMKDIR = 18; /** error code: rmdir error */ public static final int ERMDIR = 19; /** error code: miscellaneous error */ public static final int EMISC = 20; //---------------------------------------------------------------- // open modes //---------------------------------------------------------------- /** open mode: open as a reader */ public static final int OREADER = 1 << 0; /** open mode: open as a writer */ public static final int OWRITER = 1 << 1; /** open mode: writer creating */ public static final int OCREAT = 1 << 2; /** open mode: writer truncating */ public static final int OTRUNC = 1 << 3; /** open mode: open without locking */ public static final int ONOLCK = 1 << 4; /** open mode: lock without blocking */ public static final int OLCKNB = 1 << 5; /** open mode: create as a sparse file */ public static final int OSPARSE = 1 << 6; //---------------------------------------------------------------- // write modes //---------------------------------------------------------------- /** write mode: overwrite the existing value */ public static final int DOVER = 0; /** write mode: keep the existing value */ public static final int DKEEP = 1; /** write mode: concatenate values */ public static final int DCAT = 2; //---------------------------------------------------------------- // static initializer //---------------------------------------------------------------- static { try { System.loadLibrary("jqdbm"); } catch(UnsatisfiedLinkError e){ e.printStackTrace(); } dpinit(); } //---------------------------------------------------------------- // public static methods //---------------------------------------------------------------- /** * Get the version information. * @return the string of the version information. */ public static synchronized String version(){ return dpversion(); } /** * Get an error message. * @param ecode an error code. * @return the message string of the error code. */ public static synchronized String errmsg(int ecode){ return dperrmsg(ecode); } /** * Remove a database file. * @param name the name of a database file. * @throws DepotException if an error occurs. */ public static void remove(String name) throws DepotException { synchronized(ADBM.class){ if(dpremove(name) == 0) throw new DepotException(dpecode()); } } /** * Retrieve a record directly from a database file. * @param name the name of a database file. * @param key a byte array of a key. * @throws DepotException if an error occurs or no record corresponds. * @note Although this method can be used even while the database file is locked by another * process, it is not assured that recent updated is reflected. */ public static byte[] snaffle(String name, byte[] key) throws DepotException { synchronized(ADBM.class){ byte[] val = dpsnaffle(name, key, key.length); if(val == null) throw new DepotException(dpecode()); return val; } } //---------------------------------------------------------------- // instance fields //---------------------------------------------------------------- /** Whether to repress frequent exceptions. */ public boolean silent; /** Index of the native table for database handles. */ private int index; //---------------------------------------------------------------- // public or protected methods //---------------------------------------------------------------- /** * Get the database handle. * @param name the name of a database file. * @param omode the connection mode: `Depot.OWRITER' as a writer, `Depot.OREADER' as * a reader. If the mode is `Depot.OWRITER', the following may be added by bitwise or: * `Depot.OCREAT', which means it creates a new database if not exist, `Depot.OTRUNC', * which means it creates a new database regardless if one exists. Both of `Depot.OREADER' * and `Depot.OWRITER' can be added to by bitwise or: `Depot.ONOLCK', which means it opens a * database file without file locking, or `Depot.OLCKNB', which means locking is performed * without blocking. `Depot.OCREAT' can be added to by bitwise or: `Depot.OSPARSE', which * means it creates a database file as a sparse file. * @param bnum the number of elements of the bucket array. If it is not more than 0, * the default value is specified. The size of a bucket array is determined on creating, * and can not be changed except for by optimization of the database. Suggested size of a * bucket array is about from 0.5 to 4 times of the number of all records to store. * @throws DepotException if an error occurs. * @note While connecting as a writer, an exclusive lock is invoked to the database file. * While connecting as a reader, a shared lock is invoked to the database file. The thread * blocks until the lock is achieved. If `Depot.ONOLCK' is used, the application is * responsible for exclusion control. */ public Depot(String name, int omode, int bnum) throws DepotException { synchronized(ADBM.class){ silent = false; if((index = dpopen(name, omode, bnum)) == -1) throw new DepotException(dpecode()); } } /** * Get the database handle as a reader. * The same as `Depot(name, Depot.OREADER, -1)'. * @see #Depot(java.lang.String, int, int) */ public Depot(String name) throws DepotException { this(name, OREADER, -1); } /** * Release the resources. * @note If the database handle is not closed yet, it is closed. Every database should be * closed explicitly. Do not cast the duty on the gerbage collection. */ protected void finalize() throws Throwable { try { if(index < 0) return; synchronized(ADBM.class){ dpclose(index); index = -1; } } finally { super.finalize(); } } /** * Close the database handle. * @throws DepotException if an error occurs. * @note Updating a database is assured to be written when the handle is closed. If a * writer opens a database but does not close it appropriately, the database will be broken. */ public void close() throws DepotException { if(index < 0) throw new DepotException(); synchronized(ADBM.class){ int rv = dpclose(index); index = -1; if(rv == 0) throw new DepotException(dpecode()); } } /** * Store a record. * @param key a byte array of a key. * @param val a byte array of a value. * @param dmode behavior when the key overlaps, by the following values: `Depot.DOVER', * which means the specified value overwrites the existing one, `Depot.DKEEP', which means the * existing value is kept, `Depot.DCAT', which means the specified value is concatenated at * the end of the existing value. * @return always true. However, if the silent flag is true and replace is cancelled, false is * returned instead of exception. * @throws DepotException if an error occurs or replace is cancelled. */ public boolean put(byte[] key, byte[] val, int dmode) throws DepotException { if(index < 0) throw new DepotException(); synchronized(ADBM.class){ if(dpput(index, key, key.length, val, val.length, dmode) == 0){ if(silent && dpecode() == EKEEP) return false; throw new DepotException(dpecode()); } return true; } } /** * Store a record with overwrite. * The same as `put(key, val, Depot.DOVER)'. * @see #put(byte[], byte[], int) */ public boolean put(byte[] key, byte[] val) throws DepotException { return put(key, val, DOVER); } /** * Delete a record. * @param key a byte array of a key. * @return always true. However, if the silent flag is true and no record corresponds, false * is returned instead of exception. * @throws DepotException if an error occurs or no record corresponds. */ public boolean out(byte[] key) throws DepotException { if(index < 0) throw new DepotException(); synchronized(ADBM.class){ if(dpout(index, key, key.length) == 0){ if(silent && dpecode() == ENOITEM) return false; throw new DepotException(dpecode()); } return true; } } /** * Retrieve a record. * @param key a byte array of a key. * @param start the array index of the beginning of the value to be read. * @param max the max size to read with. If it is negative, the size is unlimited. * @return a byte array of the value of the corresponding record. If the silent flag is true * and no record corresponds, `null' is returned instead of exception. * @throws DepotException if an error occurs, no record corresponds, or the size of the value * of the corresponding record is less than the index specified by the parameter `start'. */ public byte[] get(byte[] key, int start, int max) throws DepotException { if(index < 0) throw new DepotException(); synchronized(ADBM.class){ byte[] val = dpget(index, key, key.length, start, max); if(val == null){ if(silent && dpecode() == ENOITEM) return null; throw new DepotException(dpecode()); } return val; } } /** * Retrieve whole value of a record. * The same as `get(key, 0, -1)'. * @see #get(byte[], int, int) */ public byte[] get(byte[] key) throws DepotException { return get(key, 0, -1); } /** * Get the size of the value of a record. * @param key a byte array of a key. * @return the size of the value of the corresponding record. If the silent flag is true and * no record corresponds, -1 is returned instead of exception. * @throws DepotException if an error occurs or no record corresponds. * @note Because this method does not read the entity of a record, it is faster than `get'. */ public int vsiz(byte[] key) throws DepotException { if(index < 0) throw new DepotException(); synchronized(ADBM.class){ int rv = dpvsiz(index, key, key.length); if(rv == -1){ if(silent && dpecode() == ENOITEM) return -1; throw new DepotException(dpecode()); } return rv; } } /** * Initialize the iterator of the database handle. * @throws DepotException if an error occurs. * @note The iterator is used in order to access the key of every record stored in a database. */ public void iterinit() throws DepotException { if(index < 0) throw new DepotException(); synchronized(ADBM.class){ if(dpiterinit(index) == 0) throw new DepotException(dpecode()); } } /** * Get the next key of the iterator. * @return a byte array of the key of the next record. If the silent flag is true and no * record corresponds, `null' is returned instead of exception. * @throws DepotException if an error occurs or no record corresponds. * @note It is possible to access every record by iteration of calling this method. * However, it is not assured if updating the database is occurred while the iteration. * Besides, the order of this traversal access method is arbitrary, so it is not assured * that the order of storing matches the one of the traversal access. */ public byte[] iternext() throws DepotException { if(index < 0) throw new DepotException(); synchronized(ADBM.class){ byte[] val = dpiternext(index); if(val == null){ if(silent && dpecode() == ENOITEM) return null; throw new DepotException(dpecode()); } return val; } } /** * Set alignment of the database handle. * @param align the basic size of alignment. * @throws DepotException if an error occurs. * @note If alignment is set to a database, the efficiency of overwriting values is improved. * The size of alignment is suggested to be average size of the values of the records to be * stored. If alignment is positive, padding whose size is multiple number of the alignment * is placed. If alignment is negative, as `vsiz' is the size of a value, the size of padding * is calculated with `(vsiz / pow(2, abs(align) - 1))'. Because alignment setting is not * saved in a database, you should specify alignment every opening a database. */ public void setalign(int align) throws DepotException { if(index < 0) throw new DepotException(); synchronized(ADBM.class){ if(dpsetalign(index, align) == 0) throw new DepotException(dpecode()); } } /** * Set the size of the free block pool. * @param size the size of the free block pool of a database. * @throws DepotException if an error occurs. * @note The default size of the free block pool is 16. If the size is greater, the space * efficiency of overwriting values is improved with the time efficiency sacrificed. */ public void setfbpsiz(int size) throws DepotException { if(index < 0) throw new DepotException(); synchronized(ADBM.class){ if(dpsetfbpsiz(index, size) == 0) throw new DepotException(dpecode()); } } /** * Synchronize updating contents with the file and the device. * @throws DepotException if an error occurs. * @note This method is useful when another process uses the connected database file. */ public void sync() throws DepotException { if(index < 0) throw new DepotException(); synchronized(ADBM.class){ if(dpsync(index) == 0) throw new DepotException(dpecode()); } } /** * Optimize the database. * @param bnum the number of the elements of the bucket array. If it is not more than 0, the * default value is specified. * @throws DepotException if an error occurs. * @note In an alternating succession of deleting and storing with overwrite or concatenate, * dispensable regions accumulate. This method is useful to do away with them. */ public void optimize(int bnum) throws DepotException { if(index < 0) throw new DepotException(); synchronized(ADBM.class){ if(dpoptimize(index, bnum) == 0) throw new DepotException(dpecode()); } } /** * Get the name of the database. * @return the string of the name of the database. * @throws DepotException if an error occurs. */ public String name() throws DepotException { if(index < 0) throw new DepotException(); synchronized(ADBM.class){ String buf = dpname(index); if(buf == null) throw new DepotException(dpecode()); return buf; } } /** * Get the size of the database file. * @return the size of the database file. * @throws DepotException if an error occurs. */ public int fsiz() throws DepotException { if(index < 0) throw new DepotException(); synchronized(ADBM.class){ int rv = dpfsiz(index); if(rv == -1) throw new DepotException(dpecode()); return rv; } } /** * Get the number of the elements of the bucket array. * @return the number of the elements of the bucket array. * @throws DepotException if an error occurs. */ public int bnum() throws DepotException { if(index < 0) throw new DepotException(); synchronized(ADBM.class){ int rv = dpbnum(index); if(rv == -1) throw new DepotException(dpecode()); return rv; } } /** * Get the number of the used elements of the bucket array. * @return the number of the used elements of the bucket array. * @throws DepotException if an error occurs. * @note This method is inefficient because it accesses all elements of the bucket array. */ public int busenum() throws DepotException { if(index < 0) throw new DepotException(); synchronized(ADBM.class){ int rv = dpbusenum(index); if(rv == -1) throw new DepotException(dpecode()); return rv; } } /** * Get the number of the records stored in the database. * @return the number of the records stored in the database. * @throws DepotException if an error occurs. */ public int rnum() throws DepotException { if(index < 0) throw new DepotException(); synchronized(ADBM.class){ int rv = dprnum(index); if(rv == -1) throw new DepotException(dpecode()); return rv; } } /** * Check whether the database handle is a writer or not. * @return true if the handle is a writer, false if not. * @throws DepotException if an error occurs. */ public boolean writable() throws DepotException { if(index < 0) throw new DepotException(); synchronized(ADBM.class){ return dpwritable(index) == 0 ? false : true; } } /** * Check whether the database has a fatal error or not. * @return true if the database has a fatal error, false if not. * @throws DepotException if an error occurs. */ public boolean fatalerror() throws DepotException { if(index < 0) throw new DepotException(); synchronized(ADBM.class){ return dpfatalerror(index) == 0 ? false : true; } } /** * Get the inode number of the database. * @return the inode number of the database file. * @throws DepotException if an error occurs. */ public int inode() throws DepotException { if(index < 0) throw new DepotException(); synchronized(ADBM.class){ return dpinode(index); } } /** * Get the last modified time of the database. * @return the last modified time of the database. * @throws DepotException if an error occurs. */ public long mtime() throws DepotException { if(index < 0) throw new DepotException(); synchronized(ADBM.class){ return dpmtime(index); } } /** * Store a record. * @param key a byte array of a key. * @param val a byte array of a value. * @param replace whether the existing value is to be overwritten or not. * @throws DepotException if an error occurs or replace is cancelled. */ public void store(byte[] key, byte[] val, boolean replace) throws DepotException { if(!put(key, val, replace ? DOVER : DKEEP)) throw new DepotException(EKEEP); } /** * Delete a record. * @param key a byte array of a key. * @throws DepotException if an error occurs or no record corresponds. */ public void delete(byte[] key) throws DepotException { if(!out(key)) throw new DepotException(ENOITEM); } /** * Fetch a record. * @param key a byte array of a key. * @return a byte array of the value of the corresponding record. * @throws DepotException if an error occurs or no record corresponds. */ public byte[] fetch(byte[] key) throws DepotException { byte[] vbuf = get(key, 0, -1); if(vbuf == null) throw new DepotException(ENOITEM); return vbuf; } /** * Get the first key. * @return a byte array of the key of the first record. * @throws DepotException if an error occurs or no record corresponds. */ public byte[] firstkey() throws DepotException { iterinit(); byte[] kbuf = iternext(); if(kbuf == null) throw new DepotException(ENOITEM); return kbuf; } /** * Get the next key. * @return a byte array of the key of the next record. * @throws DepotException if an error occurs or no record corresponds. */ public byte[] nextkey() throws DepotException { byte[] kbuf = iternext(); if(kbuf == null) throw new DepotException(ENOITEM); return kbuf; } /** * Check whether a fatal error occured or not. * @return true if the database has a fatal error, false if not. * @throws DepotException if an error occurs. */ public boolean error() throws DepotException { return fatalerror(); } //---------------------------------------------------------------- // native methods //---------------------------------------------------------------- private static synchronized final native void dpinit(); private static synchronized final native String dpversion(); private static synchronized final native int dpecode(); private static synchronized final native String dperrmsg(int ecode); private static synchronized final native int dpopen(String name, int omode, int bnum); private static synchronized final native int dpclose(int index); private static synchronized final native int dpput(int index, byte[] key, int ksiz, byte[] val, int vsiz, int dmode); private static synchronized final native int dpout(int index, byte[] key, int ksiz); private static synchronized final native byte[] dpget(int index, byte[] key, int ksiz, int start, int max); private static synchronized final native int dpvsiz(int index, byte[] key, int ksiz); private static synchronized final native int dpiterinit(int index); private static synchronized final native byte[] dpiternext(int index); private static synchronized final native int dpsetalign(int index, int align); private static synchronized final native int dpsetfbpsiz(int index, int size); private static synchronized final native int dpsync(int index); private static synchronized final native int dpoptimize(int index, int bnum); private static synchronized final native String dpname(int index); private static synchronized final native int dpfsiz(int index); private static synchronized final native int dpbnum(int index); private static synchronized final native int dpbusenum(int index); private static synchronized final native int dprnum(int index); private static synchronized final native int dpwritable(int index); private static synchronized final native int dpfatalerror(int index); private static synchronized final native int dpinode(int index); private static synchronized final native long dpmtime(int index); private static synchronized final native int dpremove(String name); private static synchronized final native byte[] dpsnaffle(String name, byte[] key, int ksiz); } /* END OF FILE */ qdbm-1.8.78/java/CuriaTester.java0000644000175000017500000002300510432047313015557 0ustar mikiomikio/************************************************************************************************* * Test cases for Curia for Java * Copyright (C) 2000-2006 Mikio Hirabayashi * This file is part of QDBM, Quick Database Manager. * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU * Lesser General Public License as published by the Free Software Foundation; either version * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * You should have received a copy of the GNU Lesser General Public License along with QDBM; if * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. *************************************************************************************************/ package qdbm; /** * Test case for Curia. */ class CuriaTester extends Thread { //---------------------------------------------------------------- // constants //---------------------------------------------------------------- private static final int LOOPNUM = 10000; private static final int LOBLOOPNUM = 1000; private static final int BUCKETNUM = 1000; private static final int LOBBUCKETNUM = 100; private static final int DBDIVNUM = 10; private static final int THREADNUM = 10; private static final java.util.Random RND = new java.util.Random(); //---------------------------------------------------------------- // class variables //---------------------------------------------------------------- private static int loopnum; private static int bucketnum; //---------------------------------------------------------------- // instance fields //---------------------------------------------------------------- private Curia mycuria; private boolean mylob; private int myid; private boolean myprinter; private CuriaException myce; //---------------------------------------------------------------- // public or protected methods //---------------------------------------------------------------- /** * Main routine. * @param args specifies a name of a database file with the first element. */ public static void main(String[] args){ if(args.length != 1){ System.err.println("usege: java qdbm.CuriaTester name"); return; } loopnum = LOOPNUM; bucketnum = BUCKETNUM; if(!dowrite(args[0], false)) System.exit(1); if(!doread(args[0], false)) System.exit(1); if(!domulti(args[0], false)) System.exit(1); loopnum = LOBLOOPNUM; bucketnum = LOBBUCKETNUM; if(!dowrite(args[0], true)) System.exit(1); if(!doread(args[0], true)) System.exit(1); if(!domulti(args[0], true)) System.exit(1); System.out.println("all ok"); System.out.println(""); System.exit(0); } /** * Perform writing test. * @param name specifies a name of a database. * @param lob specifies whether test large objects or not. * @return whether the test is success or not. */ public static boolean dowrite(String name, boolean lob){ System.out.println(""); System.out.println(" name=" + name + " lob=" + lob); System.out.println(""); Curia curia = null; boolean err = false; try { // open a database System.out.print("Creating ... "); curia = new Curia(name, Curia.OWRITER | Curia.OCREAT | Curia.OTRUNC, bucketnum, DBDIVNUM); System.out.println("ok"); // loop for storing System.out.println("Writing"); for(int i = 1; i <= loopnum; i++){ byte[] buf = Util.numstr(i, 8, '0').getBytes(); // store a record into the database if(lob){ curia.putlob(buf, buf, Curia.DOVER); } else { curia.put(buf, buf, Curia.DOVER); } // print progression if(i % (loopnum / 250) == 0){ System.out.print('.'); System.out.flush(); if(i == loopnum || i % (loopnum / 10) == 0){ System.out.println(" (" + new String(buf) + ")"); System.out.flush(); } } } System.out.println("ok"); } catch(CuriaException e){ err = true; // report an error System.err.println(e); } finally { try { // close the database System.out.print("Closing ... "); if(curia != null) curia.close(); System.out.println("ok"); } catch(CuriaException e){} } System.out.println(""); return err ? false : true; } /** * Perform reading test. * @param name specifies a name of a database. * @param lob specifies whether test large objects or not. * @return whether the test is success or not. */ public static boolean doread(String name, boolean lob){ System.out.println(""); System.out.println(" name=" + name + " lob=" + lob); System.out.println(""); Curia curia = null; boolean err = false; try { // open a database System.out.print("Opening ... "); curia = new Curia(name); System.out.println("ok"); System.out.println("Reading"); // loop for retrieving for(int i = 1; i <= loopnum; i++){ byte[] buf = Util.numstr(i, 8, '0').getBytes(); // retrieve a record from the database if(lob){ curia.getlob(buf, 0, -1); } else { curia.get(buf, 0, -1); } // print progression if(i % (loopnum / 250) == 0){ System.out.print('.'); System.out.flush(); if(i == loopnum || i % (loopnum / 10) == 0){ System.out.println(" (" + new String(buf) + ")"); System.out.flush(); } } } System.out.println("ok"); } catch(CuriaException e){ err = true; // report an error System.err.println(e); } finally { try { // close the database System.out.print("Closing ... "); if(curia != null) curia.close(); System.out.println("ok"); } catch(CuriaException e){} } System.out.println(""); return err ? false : true; } /** * Perform multi thread test. * @param name specifies a name of a database. * @param lob specifies whether test large objects or not. * @return whether the test is success or not. */ public static boolean domulti(String name, boolean lob){ System.out.println(""); System.out.println(" name=" + name + " lob=" + lob); System.out.println(""); Curia curia = null; boolean err = false; try { // open a database System.out.print("Opening ... "); curia = new Curia(name, Curia.OWRITER | Curia.OCREAT | Curia.OTRUNC, bucketnum, DBDIVNUM); System.out.println("ok"); // prepare threads CuriaTester[] dts = new CuriaTester[THREADNUM]; // roop for each threads System.out.println("Writing"); for(int i = 0; i < dts.length; i++){ dts[i] = new CuriaTester(curia, lob, i, i == dts.length / 2); dts[i].start(); } // join every threads for(int i = 0; i < dts.length; i++){ try { dts[i].join(); if(dts[i].myce != null){ err = true; System.err.println(dts[i].myce); } } catch(InterruptedException e){ i--; } } if(!err) System.out.println("ok"); System.out.flush(); // check every record System.out.print("Validation checking ... "); for(int i = 1; i <= loopnum; i++){ byte[] buf = Util.numstr(i, 8, '0').getBytes(); byte[] val; if(lob){ val = curia.getlob(buf, 0, -1); } else { val = curia.get(buf, 0, -1); } if(val.length != THREADNUM){ err = true; System.err.println("size error: " + val.length); } } if(!err) System.out.println("ok"); } catch(CuriaException e){ err = true; System.err.println(e); } finally { try { // close the database System.out.print("Closing ... "); if(curia != null) curia.close(); System.out.println("ok"); } catch(CuriaException e){} } System.out.println(""); return err ? false : true; } /** * Constructor for multi thread test. */ private CuriaTester(Curia curia, boolean lob, int id, boolean printer){ mycuria = curia; mylob = lob; myid = id; myprinter = printer; myce = null; } /** * Method for multi thread test. */ public void run(){ // roop for storing for(int i = 1; i <= loopnum; i++){ // store a record into the database byte[] buf = Util.numstr(i, 8, '0').getBytes(); try { if(RND.nextInt(LOOPNUM / 20) == 0) yield(); if(mylob){ mycuria.putlob(buf, (myid % 2 == 0 ? "=" : "*").getBytes(), Curia.DCAT); } else { mycuria.put(buf, (myid % 2 == 0 ? "=" : "*").getBytes(), Curia.DCAT); } } catch(CuriaException e){ myce = e; return; } // print progression if(myprinter && i % (loopnum / 250) == 0){ System.out.print('.'); System.out.flush(); if(i == loopnum || i % (loopnum / 10) == 0){ System.out.println(" (" + new String(buf) + ")"); System.out.flush(); // garbage collection test System.gc(); } } } } } /* END OF FILE */ qdbm-1.8.78/java/Doxyfile0000644000175000017500000000227310572737753014217 0ustar mikiomikio# Doxyfile for Java API of QDBM # General configuration options PROJECT_NAME = "QDBM for Java" OUTPUT_LANGUAGE = English EXTRACT_ALL = NO EXTRACT_PRIVATE = NO EXTRACT_STATIC = NO SHOW_INCLUDE_FILES = NO VERBATIM_HEADERS = NO JAVADOC_AUTOBRIEF = YES DETAILS_AT_TOP = YES INLINE_INFO = NO OPTIMIZE_OUTPUT_FOR_C = NO OPTIMIZE_OUTPUT_JAVA = YES QUIET = YES WARNINGS = YES # Configuration options related to the input files INPUT = . FILE_PATTERNS = overview ADBM.java DBMException.java Util.java \ Depot.java DepotException.java \ Curia.java CuriaException.java \ Villa.java VillaException.java RECURSIVE = NO # Configuration options related to the HTML output GENERATE_HTML = YES HTML_OUTPUT = japidoc HTML_FILE_EXTENSION = .html GENERATE_TREEVIEW = YES TREEVIEW_WIDTH = 250 # Configuration options related to the LaTeX output GENERATE_LATEX = NO LATEX_OUTPUT = latex # Configuration options related to the man page output GENERATE_MAN = NO MAN_OUTPUT = man MAN_EXTENSION = .3 # Configuration options related to the dot tool #HAVE_DOT = YES #CLASS_GRAPH = YES #COLLABORATION_GRAPH = NO #INCLUDE_GRAPH = NO #INCLUDED_BY_GRAPH = NO #GRAPHICAL_HIERARCHY = YES #GENERATE_LEGEND = NO # END OF FILE qdbm-1.8.78/java/VillaCursor.java0000644000175000017500000002347010505430214015575 0ustar mikiomikio/************************************************************************************************* * The Java API of cursor functions of Villa * Copyright (C) 2000-2006 Mikio Hirabayashi * This file is part of QDBM, Quick Database Manager. * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU * Lesser General Public License as published by the Free Software Foundation; either version * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * You should have received a copy of the GNU Lesser General Public License along with QDBM; if * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. *************************************************************************************************/ package qdbm; /** * The Java API of cursor functions of Villa * This class depends on the native library `jqdbm'. */ public class VillaCursor { //---------------------------------------------------------------- // instance fields //---------------------------------------------------------------- /** pointer to the native object */ private long coreptr; /** database handle */ private Villa villa; //---------------------------------------------------------------- // constructors and finalizers //---------------------------------------------------------------- /** * Get a multiple cursor handle. * @param villa a database handle connected as a reader. * @throws VillaException if an error occurs. */ VillaCursor(Villa villa) throws VillaException { this.villa = villa; synchronized(ADBM.class){ int index = villa.getindex(); if(index < 0) throw new VillaException(); if(vlmulcurnew(index) == 0) throw new VillaException(vlmulcurecode()); } } /** * Release resources. */ protected void finalize(){ vlmulcurdelete(); } //---------------------------------------------------------------- // public or protected methods //---------------------------------------------------------------- /** * Move the multiple cursor to the first record. * @return always true. However, if the silent flag is true and no record corresponds, false * is returned instead of exception. * @throws VillaException if an error occurs or there is no record in the database. */ public boolean first() throws VillaException { synchronized(ADBM.class){ int index = villa.getindex(); if(index < 0) throw new VillaException(); if(vlmulcurfirst(index) == 0){ if(villa.silent && vlmulcurecode() == Villa.ENOITEM) return false; throw new VillaException(vlmulcurecode()); } return true; } } /** * Move the multiple cursor to the last record. * @return always true. However, if the silent flag is true and no record corresponds, false * is returned instead of exception. * @throws VillaException if an error occurs or there is no record in the database. */ public boolean last() throws VillaException { synchronized(ADBM.class){ int index = villa.getindex(); if(index < 0) throw new VillaException(); if(vlmulcurlast(index) == 0){ if(villa.silent && vlmulcurecode() == Villa.ENOITEM) return false; throw new VillaException(vlmulcurecode()); } return true; } } /** * Move the multiple cursor to the next record. * @return always true. However, if the silent flag is true and no record corresponds, false * is returned instead of exception. * @throws VillaException if an error occurs or there is no previous record. */ public boolean prev() throws VillaException { synchronized(ADBM.class){ int index = villa.getindex(); if(index < 0) throw new VillaException(); if(vlmulcurprev(index) == 0){ if(villa.silent && vlmulcurecode() == Villa.ENOITEM) return false; throw new VillaException(vlmulcurecode()); } return true; } } /** * Move the multiple cursor to the next record. * @return always true. However, if the silent flag is true and no record corresponds, false * is returned instead of exception. * @throws VillaException if an error occurs or there is no next record. */ public boolean next() throws VillaException { synchronized(ADBM.class){ int index = villa.getindex(); if(index < 0) throw new VillaException(); if(vlmulcurnext(index) == 0){ if(villa.silent && vlmulcurecode() == Villa.ENOITEM) return false; throw new VillaException(vlmulcurecode()); } return true; } } /** * Move the multiple cursor to a position around a record. * @param key a byte array of a key. * @param jmode detail adjustment: `Villa.JFORWARD', which means that the cursor is set to * the first record of the same key and that the cursor is set to the next substitute if * completely matching record does not exist, `Villa.JBACKWARD', which means that the cursor * is set to the last record of the same key and that the cursor is set to the previous * substitute if completely matching record does not exist. * @return always true. However, if the silent flag is true and no record corresponds, false * is returned instead of exception. * @throws VillaException if an error occurs or there is no record corresponding the condition. */ public boolean jump(byte[] key, int jmode) throws VillaException { synchronized(ADBM.class){ int index = villa.getindex(); if(index < 0) throw new VillaException(); if(vlmulcurjump(index, key, key.length, jmode) == 0){ if(villa.silent && vlmulcurecode() == Villa.ENOITEM) return false; throw new VillaException(vlmulcurecode()); } return true; } } /** * Move the multiple cursor to a position around a record for stepping forward. * The same as `jump(key, Villa.JFORFARD)'. * @see #jump(byte[], int) */ public boolean jump(byte[] key) throws VillaException { return jump(key, Villa.JFORWARD); } /** * Move the multiple cursor to a position around a record composed of serializable objects. * The same as `jump(qdbm.Util.serialize(key), jmode)'. * @see #jump(byte[], int) * @note If serialization is failed, an instance of `VillaException' is thrown. */ public boolean jumpobj(Object key, int jmode) throws VillaException { byte[] kbuf = Util.serialize(key); if(kbuf == null) throw new VillaException(); return jump(kbuf, jmode); } /** * Get the key of the record where the multiple cursor is. * @return a byte array of the key of the corresponding record. If the silent flag is true and * no record corresponds, `null' is returned instead of exception. * @throws VillaException if an error occurs or no record corresponds to the cursor. */ public byte[] key() throws VillaException { synchronized(ADBM.class){ int index = villa.getindex(); if(index < 0) throw new VillaException(); byte[] val = vlmulcurkey(index); if(val == null){ if(villa.silent && vlmulcurecode() == Villa.ENOITEM) return null; throw new VillaException(vlmulcurecode()); } return val; } } /** * Get the key of the record composed of serializable objects, where the multiple cursor is. * The same as `qdbm.Util.deserialize(key())'. * @see #key() * @note If serialization is failed, an instance of `VillaException' is thrown. */ public Object keyobj() throws VillaException { byte[] kbuf = key(); if(kbuf == null) return null; Object key = Util.deserialize(kbuf); if(key == null) throw new VillaException(); return key; } /** * Get the value of the record where the multiple cursor is. * @return a byte array of the value of the corresponding record. If the silent flag is true * and no record corresponds, `null' is returned instead of exception. * @throws VillaException if an error occurs or no record corresponds to the cursor. */ public byte[] val() throws VillaException { synchronized(ADBM.class){ int index = villa.getindex(); if(index < 0) throw new VillaException(); byte[] val = vlmulcurval(index); if(val == null){ if(villa.silent && vlmulcurecode() == Villa.ENOITEM) return null; throw new VillaException(vlmulcurecode()); } return val; } } /** * Get the value of the record where the multiple cursor is. * The same as `qdbm.Util.deserialize(val())'. * @see #val() * @note If serialization is failed, an instance of `VillaException' is thrown. */ public Object valobj() throws VillaException { byte[] vbuf = val(); if(vbuf == null) return vbuf; Object val = Util.deserialize(vbuf); if(val == null) throw new VillaException(); return val; } //---------------------------------------------------------------- // native methods //---------------------------------------------------------------- private static synchronized final native int vlmulcurecode(); private synchronized final native int vlmulcurnew(int index); private synchronized final native void vlmulcurdelete(); private synchronized final native int vlmulcurfirst(int index); private synchronized final native int vlmulcurlast(int index); private synchronized final native int vlmulcurprev(int index); private synchronized final native int vlmulcurnext(int index); private synchronized final native int vlmulcurjump(int index, byte[] key, int ksiz, int jmode); private synchronized final native byte[] vlmulcurkey(int index); private synchronized final native byte[] vlmulcurval(int index); } /* END OF FILE */ qdbm-1.8.78/java/japidoc/0000755000175000017500000000000011426320065014075 5ustar mikiomikioqdbm-1.8.78/java/japidoc/serialized-form.html0000644000175000017500000001645111426320065020066 0ustar mikiomikio Serialized Form (qdbm)

Serialized Form


Package qdbm

Class qdbm.CuriaException extends DBMException implements Serializable

Serialized Fields

ecode

int ecode
error code

Class qdbm.DBMException extends java.lang.Exception implements Serializable

Class qdbm.DepotException extends DBMException implements Serializable

Serialized Fields

ecode

int ecode
error code

Class qdbm.VillaException extends DBMException implements Serializable

Serialized Fields

ecode

int ecode
error code



qdbm-1.8.78/java/japidoc/resources/0000755000175000017500000000000011426320065016107 5ustar mikiomikioqdbm-1.8.78/java/japidoc/resources/inherit.gif0000644000175000017500000000007111426320065020236 0ustar mikiomikioGIF89a€ÿÿÿ,„ ¡½®DršjñÔ;߀Q@–¦…N;qdbm-1.8.78/java/japidoc/stylesheet.css0000644000175000017500000000255711426320065017011 0ustar mikiomikio/* Javadoc style sheet */ /* Define colors, fonts and other style attributes here to override the defaults */ /* Page background color */ body { background-color: #FFFFFF; color:#000000 } /* Headings */ h1 { font-size: 145% } /* Table colors */ .TableHeadingColor { background: #CCCCFF; color:#000000 } /* Dark mauve */ .TableSubHeadingColor { background: #EEEEFF; color:#000000 } /* Light mauve */ .TableRowColor { background: #FFFFFF; color:#000000 } /* White */ /* Font used in left-hand frame lists */ .FrameTitleFont { font-size: 100%; font-family: Helvetica, Arial, sans-serif; color:#000000 } .FrameHeadingFont { font-size: 90%; font-family: Helvetica, Arial, sans-serif; color:#000000 } .FrameItemFont { font-size: 90%; font-family: Helvetica, Arial, sans-serif; color:#000000 } /* Navigation bar fonts and colors */ .NavBarCell1 { background-color:#EEEEFF; color:#000000} /* Light mauve */ .NavBarCell1Rev { background-color:#00008B; color:#FFFFFF} /* Dark Blue */ .NavBarFont1 { font-family: Arial, Helvetica, sans-serif; color:#000000;color:#000000;} .NavBarFont1Rev { font-family: Arial, Helvetica, sans-serif; color:#FFFFFF;color:#FFFFFF;} .NavBarCell2 { font-family: Arial, Helvetica, sans-serif; background-color:#FFFFFF; color:#000000} .NavBarCell3 { font-family: Arial, Helvetica, sans-serif; background-color:#FFFFFF; color:#000000} qdbm-1.8.78/java/japidoc/overview-tree.html0000644000175000017500000001345611426320065017577 0ustar mikiomikio Class Hierarchy (qdbm)

Hierarchy For All Packages

Package Hierarchies:
qdbm

Class Hierarchy

Interface Hierarchy



qdbm-1.8.78/java/japidoc/overview-summary.html0000644000175000017500000001507711426320065020336 0ustar mikiomikio Overview (qdbm)

QDBM: Quick Database Manager.

See:
          Description

Packages
qdbm  

 

QDBM: Quick Database Manager.

QDBM is a library of routines for managing a database. The database is a simple data file containing records, each is a pair of a key and a value. Every key and value is serial bytes with variable length. Both binary data and character string can be used as a key and a value. There is neither concept of data tables nor data types. Records are organazed in hash table or B+ tree.

As for database of hash table, each key must be unique within a database, so it is impossible to store two or more records with a key overlaps. The following access methods are provided to the database: storing a record with a key and a value, deleting a record by a key, retrieving a record by a key. Moreover, traversal access to every key are provided, although the order is arbitrary. These access methods are similar to ones of DBM (or its followers, NDBM and GDBM) library defined in the UNIX standard. QDBM is an alternative for DBM because of its higher performance.

As for database of B+ tree, records whose keys are duplicated can be stored. Access methods of storing, deleting and retrieving are provided as with the database of hash table. Records are stored in order by a comparing function assigned by a user. It is possible to access each record with the cursor in ascending or descending order. According to this mechanism, forward matching search for strings and range search for integers are realized. Moreover, transaction is available in database of B+ tree.

This package is Java API for QDBM. This package contains native methods which are depends on native libraries of QDBM. Each class is packaged in `qdbm'.

Refer to `http://fallabs.com/qdbm/' for more information.



qdbm-1.8.78/java/japidoc/index.html0000644000175000017500000000232111426320065016070 0ustar mikiomikio qdbm <H2> Frame Alert</H2> <P> This document is designed to be viewed using the frames feature. If you see this message, you are using a non-frame-capable web client. <BR> Link to<A HREF="overview-summary.html">Non-frame version.</A> qdbm-1.8.78/java/japidoc/qdbm/0000755000175000017500000000000011426320065015020 5ustar mikiomikioqdbm-1.8.78/java/japidoc/qdbm/DBMException.html0000644000175000017500000002226411426320065020175 0ustar mikiomikio DBMException (qdbm)

qdbm
Class DBMException

java.lang.Object
  extended by java.lang.Throwable
      extended by java.lang.Exception
          extended by qdbm.DBMException
All Implemented Interfaces:
java.io.Serializable
Direct Known Subclasses:
CuriaException, DepotException, VillaException

public class DBMException
extends java.lang.Exception

Exception container of ADBM.

See Also:
Serialized Form

Constructor Summary
DBMException()
          Nothing specified.
DBMException(java.lang.String message)
          Nothing specified.
 
Method Summary
 
Methods inherited from class java.lang.Throwable
fillInStackTrace, getCause, getLocalizedMessage, getMessage, getStackTrace, initCause, printStackTrace, printStackTrace, printStackTrace, setStackTrace, toString
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
 

Constructor Detail

DBMException

public DBMException()
Nothing specified.


DBMException

public DBMException(java.lang.String message)
Nothing specified.



qdbm-1.8.78/java/japidoc/qdbm/Curia.html0000644000175000017500000021423511426320065016760 0ustar mikiomikio Curia (qdbm)

qdbm
Class Curia

java.lang.Object
  extended by qdbm.Curia
All Implemented Interfaces:
ADBM

public class Curia
extends java.lang.Object
implements ADBM

The Java API of Curia, the extended API of QDBM. This class depends on the native library `jqdbm'.


Field Summary
static int DCAT
          write mode: concatenate values
static int DKEEP
          write mode: keep the existing value
static int DOVER
          write mode: overwrite the existing value
static int EALLOC
          error code: memory allocation error
static int EBROKEN
          error code: broken database file
static int ECLOSE
          error code: close error
static int EFATAL
          error code: with fatal error
static int EKEEP
          error code: existing record
static int ELOCK
          error code: lock error
static int EMAP
          error code: memory mapping error
static int EMISC
          error code: miscellaneous error
static int EMKDIR
          error code: mkdir error
static int EMODE
          error code: invalid mode
static int ENOERR
          error code: no error
static int ENOITEM
          error code: no item found
static int EOPEN
          error code: open error
static int EREAD
          error code: read error
static int ERMDIR
          error code: rmdir error
static int ESEEK
          error code: seek error
static int ESTAT
          error code: stat error
static int ESYNC
          error code: sync error
static int ETRUNC
          error code: trunc error
static int EUNLINK
          error code: unlink error
static int EWRITE
          error code: write error
static int OCREAT
          open mode: writer creating
static int OLCKNB
          open mode: lock without blocking
static int ONOLCK
          open mode: open without locking
static int OREADER
          open mode: open as a reader
static int OSPARSE
          open mode: create as sparse files
static int OTRUNC
          open mode: writer truncating
static int OWRITER
          open mode: open as a writer
 boolean silent
          Whether to repress frequent exceptions.
 
Constructor Summary
Curia(java.lang.String name)
          Get the database handle as a reader.
Curia(java.lang.String name, int omode, int bnum, int dnum)
          Get the database handle.
 
Method Summary
 int bnum()
          Get the total number of the elements of each bucket array.
 int busenum()
          Get the total number of the used elements of each bucket array.
 void close()
          Close the database handle.
 void delete(byte[] key)
          Delete a record.
static java.lang.String errmsg(int ecode)
          Get an error message.
 boolean error()
          Check whether a fatal error occured or not.
 boolean fatalerror()
          Check whether the database has a fatal error or not.
 byte[] fetch(byte[] key)
          Fetch a record.
protected  void finalize()
          Release the resources.
 byte[] firstkey()
          Get the first key.
 long fsiz()
          Get the total size of the database files.
 byte[] get(byte[] key)
          Retrieve whole value of a record.
 byte[] get(byte[] key, int start, int max)
          Retrieve a record.
 byte[] getlob(byte[] key)
          Retrieve whole value of a large object.
 byte[] getlob(byte[] key, int start, int max)
          Retrieve a large object.
 int inode()
          Get the inode number of the database.
 void iterinit()
          Initialize the iterator of the database handle.
 byte[] iternext()
          Get the next key of the iterator.
 long mtime()
          Get the last modified time of the database.
 java.lang.String name()
          Get the name of the database.
 byte[] nextkey()
          Get the next key.
 void optimize(int bnum)
          Optimize the database.
 boolean out(byte[] key)
          Delete a record.
 boolean outlob(byte[] key)
          Delete a large object.
 boolean put(byte[] key, byte[] val)
          Store a record with overwrite.
 boolean put(byte[] key, byte[] val, int dmode)
          Store a record.
 boolean putlob(byte[] key, byte[] val)
          Store a large object with overwrite.
 boolean putlob(byte[] key, byte[] val, int dmode)
          Store a large object.
static void remove(java.lang.String name)
          Remove a database directory.
 int rnum()
          Get the number of the records stored in the database.
 int rnumlob()
          Get the number of the large objects stored in the database.
 void setalign(int align)
          Set alignment of the database handle.
 void setfbpsiz(int size)
          Set the size of the free block pool.
static byte[] snaffle(java.lang.String name, byte[] key)
          Retrieve a record directly from a database directory.
 void store(byte[] key, byte[] val, boolean replace)
          Store a record.
 void sync()
          Synchronize updating contents with the files and the devices.
static java.lang.String version()
          Get the version information.
 int vsiz(byte[] key)
          Get the size of the value of a record.
 int vsizlob(byte[] key)
          Get the size of the value of a large object.
 boolean writable()
          Check whether the database handle is a writer or not.
 
Methods inherited from class java.lang.Object
clone, equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

DCAT

public static final int DCAT
write mode: concatenate values

See Also:
Constant Field Values

DKEEP

public static final int DKEEP
write mode: keep the existing value

See Also:
Constant Field Values

DOVER

public static final int DOVER
write mode: overwrite the existing value

See Also:
Constant Field Values

EALLOC

public static final int EALLOC
error code: memory allocation error

See Also:
Constant Field Values

EBROKEN

public static final int EBROKEN
error code: broken database file

See Also:
Constant Field Values

ECLOSE

public static final int ECLOSE
error code: close error

See Also:
Constant Field Values

EFATAL

public static final int EFATAL
error code: with fatal error

See Also:
Constant Field Values

EKEEP

public static final int EKEEP
error code: existing record

See Also:
Constant Field Values

ELOCK

public static final int ELOCK
error code: lock error

See Also:
Constant Field Values

EMAP

public static final int EMAP
error code: memory mapping error

See Also:
Constant Field Values

EMISC

public static final int EMISC
error code: miscellaneous error

See Also:
Constant Field Values

EMKDIR

public static final int EMKDIR
error code: mkdir error

See Also:
Constant Field Values

EMODE

public static final int EMODE
error code: invalid mode

See Also:
Constant Field Values

ENOERR

public static final int ENOERR
error code: no error

See Also:
Constant Field Values

ENOITEM

public static final int ENOITEM
error code: no item found

See Also:
Constant Field Values

EOPEN

public static final int EOPEN
error code: open error

See Also:
Constant Field Values

EREAD

public static final int EREAD
error code: read error

See Also:
Constant Field Values

ERMDIR

public static final int ERMDIR
error code: rmdir error

See Also:
Constant Field Values

ESEEK

public static final int ESEEK
error code: seek error

See Also:
Constant Field Values

ESTAT

public static final int ESTAT
error code: stat error

See Also:
Constant Field Values

ESYNC

public static final int ESYNC
error code: sync error

See Also:
Constant Field Values

ETRUNC

public static final int ETRUNC
error code: trunc error

See Also:
Constant Field Values

EUNLINK

public static final int EUNLINK
error code: unlink error

See Also:
Constant Field Values

EWRITE

public static final int EWRITE
error code: write error

See Also:
Constant Field Values

OCREAT

public static final int OCREAT
open mode: writer creating

See Also:
Constant Field Values

OLCKNB

public static final int OLCKNB
open mode: lock without blocking

See Also:
Constant Field Values

ONOLCK

public static final int ONOLCK
open mode: open without locking

See Also:
Constant Field Values

OREADER

public static final int OREADER
open mode: open as a reader

See Also:
Constant Field Values

OSPARSE

public static final int OSPARSE
open mode: create as sparse files

See Also:
Constant Field Values

OTRUNC

public static final int OTRUNC
open mode: writer truncating

See Also:
Constant Field Values

OWRITER

public static final int OWRITER
open mode: open as a writer

See Also:
Constant Field Values

silent

public boolean silent
Whether to repress frequent exceptions.

Constructor Detail

Curia

public Curia(java.lang.String name)
      throws CuriaException
Get the database handle as a reader. The same as `Curia(name, Curia.OREADER, -1)'.

Throws:
CuriaException
See Also:
Curia(java.lang.String, int, int, int)

Curia

public Curia(java.lang.String name,
             int omode,
             int bnum,
             int dnum)
      throws CuriaException
Get the database handle.

Parameters:
name - the name of a database directory.
omode - the connection mode: `Curia.OWRITER' as a writer, `Curia.OREADER' as a reader. If the mode is `Curia.OWRITER', the following may be added by bitwise or: `Curia.OCREAT', which means it creates a new database if not exist, `Curia.OTRUNC', which means it creates a new database regardless if one exists. Both of `Curia.OREADER' and `Curia.OWRITER' can be added to by bitwise or: `Curia.ONOLCK', which means it opens a database directory without file locking, or `Curia.OLCKNB', which means locking is performed without blocking. `Curia.OCREAT' can be added to by bitwise or: `Curia.OSPARSE', which means it creates database files as sparse files.
bnum - the number of elements of the each bucket array. If it is not more than 0, the default value is specified. The size of each bucket array is determined on creating, and can not be changed except for by optimization of the database. Suggested size of each bucket array is about from 0.5 to 4 times of the number of all records to store.
dnum - the number of division of the database. If it is not more than 0, the default value is specified. The number of division can not be changed from the initial value. The max number of division is 512.
Throws:
CuriaException - if an error occurs.
Note:
While connecting as a writer, an exclusive lock is invoked to the database directory. While connecting as a reader, a shared lock is invoked to the database directory. The thread blocks until the lock is achieved. If `Curia.ONOLCK' is used, the application is responsible for exclusion control.
Method Detail

bnum

public int bnum()
         throws CuriaException
Get the total number of the elements of each bucket array.

Returns:
the total number of the elements of each bucket array.
Throws:
CuriaException - if an error occurs.

busenum

public int busenum()
            throws CuriaException
Get the total number of the used elements of each bucket array.

Returns:
the total number of the used elements of each bucket array.
Throws:
CuriaException - if an error occurs.
Note:
This method is inefficient because it accesses all elements of each bucket array.

close

public void close()
           throws CuriaException
Close the database handle.

Specified by:
close in interface ADBM
Throws:
CuriaException - if an error occurs.
Note:
Updating a database is assured to be written when the handle is closed. If a writer opens a database but does not close it appropriately, the database will be broken.

delete

public void delete(byte[] key)
            throws CuriaException
Delete a record.

Specified by:
delete in interface ADBM
Parameters:
key - a byte array of a key.
Throws:
CuriaException - if an error occurs or no record corresponds.

errmsg

public static java.lang.String errmsg(int ecode)
Get an error message.

Parameters:
ecode - an error code.
Returns:
the message string of the error code.

error

public boolean error()
              throws CuriaException
Check whether a fatal error occured or not.

Specified by:
error in interface ADBM
Returns:
true if the database has a fatal error, false if not.
Throws:
CuriaException - if an error occurs.

fatalerror

public boolean fatalerror()
                   throws CuriaException
Check whether the database has a fatal error or not.

Returns:
true if the database has a fatal error, false if not.
Throws:
CuriaException - if an error occurs.

fetch

public byte[] fetch(byte[] key)
             throws CuriaException
Fetch a record.

Specified by:
fetch in interface ADBM
Parameters:
key - a byte array of a key.
Returns:
a byte array of the value of the corresponding record.
Throws:
CuriaException - if an error occurs or no record corresponds.

finalize

protected void finalize()
                 throws java.lang.Throwable
Release the resources.

Overrides:
finalize in class java.lang.Object
Throws:
java.lang.Throwable
Note:
If the database handle is not closed yet, it is closed. Every database should be closed explicitly. Do not cast the duty on the gerbage collection.

firstkey

public byte[] firstkey()
                throws CuriaException
Get the first key.

Specified by:
firstkey in interface ADBM
Returns:
a byte array of the key of the first record.
Throws:
CuriaException - if an error occurs or no record corresponds.

fsiz

public long fsiz()
          throws CuriaException
Get the total size of the database files.

Returns:
the total size of the database files.
Throws:
CuriaException - if an error occurs.

get

public byte[] get(byte[] key)
           throws CuriaException
Retrieve whole value of a record. The same as `get(key, 0, -1)'.

Throws:
CuriaException
See Also:
get(byte[], int, int)

get

public byte[] get(byte[] key,
                  int start,
                  int max)
           throws CuriaException
Retrieve a record.

Parameters:
key - a byte array of a key.
start - the array index of the beginning of the value to be read.
max - the max size to read with. If it is negative, the size is unlimited.
Returns:
a byte array of the value of the corresponding record. If the silent flag is true and no record corresponds, `null' is returned instead of exception.
Throws:
CuriaException - if an error occurs, no record corresponds, or the size of the value of the corresponding record is less than the index specified by the parameter `start'.

getlob

public byte[] getlob(byte[] key)
              throws CuriaException
Retrieve whole value of a large object. The same as `get(key, 0, -1)'.

Throws:
CuriaException
See Also:
get(byte[], int, int)

getlob

public byte[] getlob(byte[] key,
                     int start,
                     int max)
              throws CuriaException
Retrieve a large object.

Parameters:
key - a byte array of a key.
start - the array index of the beginning of the value to be read.
max - the max size to be read. If it is negative, the size to read is unlimited.
Returns:
a byte array of the value of the corresponding large object. If the silent flag is true and no record corresponds, `null' is returned instead of exception.
Throws:
CuriaException - if an error occurs, no large object corresponds or the size of the value of the corresponding is less than the index specified by the parameter `start'.

inode

public int inode()
          throws CuriaException
Get the inode number of the database.

Returns:
the inode number of the database directory.
Throws:
CuriaException - if an error occurs.

iterinit

public void iterinit()
              throws CuriaException
Initialize the iterator of the database handle.

Throws:
CuriaException - if an error occurs.
Note:
The iterator is used in order to access the key of every record stored in a database.

iternext

public byte[] iternext()
                throws CuriaException
Get the next key of the iterator.

Returns:
a byte array of the key of the next record. If the silent flag is true and no record corresponds, `null' is returned instead of exception.
Throws:
CuriaException - if an error occurs or no record corresponds.
Note:
It is possible to access every record by iteration of calling this method. However, it is not assured if updating the database is occurred while the iteration. Besides, the order of this traversal access method is arbitrary, so it is not assured that the order of storing matches the one of the traversal access.

mtime

public long mtime()
           throws CuriaException
Get the last modified time of the database.

Returns:
the last modified time of the database.
Throws:
CuriaException - if an error occurs.

name

public java.lang.String name()
                      throws CuriaException
Get the name of the database.

Returns:
the string of the name of the database.
Throws:
CuriaException - if an error occurs.

nextkey

public byte[] nextkey()
               throws CuriaException
Get the next key.

Specified by:
nextkey in interface ADBM
Returns:
a byte array of the key of the next record.
Throws:
CuriaException - if an error occurs or no record corresponds.

optimize

public void optimize(int bnum)
              throws CuriaException
Optimize the database.

Parameters:
bnum - the number of the elements of each bucket array. If it is not more than 0, the default value is specified.
Throws:
CuriaException - if an error occurs.
Note:
In an alternating succession of deleting and storing with overwrite or concatenate, dispensable regions accumulate. This method is useful to do away with them.

out

public boolean out(byte[] key)
            throws CuriaException
Delete a record.

Parameters:
key - a byte array of a key.
Returns:
always true. However, if the silent flag is true and no record corresponds, false is returned instead of exception.
Throws:
CuriaException - if an error occurs or no record corresponds.

outlob

public boolean outlob(byte[] key)
               throws CuriaException
Delete a large object.

Parameters:
key - a byte array of a key.
Returns:
always true. However, if the silent flag is true and no record corresponds, false is returned instead of exception.
Throws:
CuriaException - if an error occurs or no large object corresponds.

put

public boolean put(byte[] key,
                   byte[] val)
            throws CuriaException
Store a record with overwrite. The same as `put(key, val, Curia.DOVER)'.

Throws:
CuriaException
See Also:
put(byte[], byte[], int)

put

public boolean put(byte[] key,
                   byte[] val,
                   int dmode)
            throws CuriaException
Store a record.

Parameters:
key - a byte array of a key.
val - a byte array of a value.
dmode - behavior when the key overlaps, by the following values: `Curia.DOVER', which means the specified value overwrites the existing one, `Curia.DKEEP', which means the existing value is kept, `Curia.DCAT', which means the specified value is concatenated at the end of the existing value.
Returns:
always true. However, if the silent flag is true and replace is cancelled, false is returned instead of exception.
Throws:
CuriaException - if an error occurs or replace is cancelled.

putlob

public boolean putlob(byte[] key,
                      byte[] val)
               throws CuriaException
Store a large object with overwrite. The same as `putlob(key, val, Curia.DOVER)'.

Throws:
CuriaException
See Also:
put(byte[], byte[], int)

putlob

public boolean putlob(byte[] key,
                      byte[] val,
                      int dmode)
               throws CuriaException
Store a large object.

Parameters:
key - a byte array of a key.
val - a byte array of a value.
dmode - behavior when the key overlaps, by the following values: `Curia.DOVER', which means the specified value overwrites the existing one, `Curia.DKEEP', which means the existing value is kept, `Curia.DCAT', which means the specified value is concatenated at the end of the existing value.
Returns:
always true. However, if the silent flag is true and replace is cancelled, false is returned instead of exception.
Throws:
CuriaException - if an error occurs or replace is cancelled.

remove

public static void remove(java.lang.String name)
                   throws CuriaException
Remove a database directory.

Parameters:
name - the name of a database directory.
Throws:
CuriaException - if an error occurs.

rnum

public int rnum()
         throws CuriaException
Get the number of the records stored in the database.

Returns:
the number of the records stored in the database.
Throws:
CuriaException - if an error occurs.

rnumlob

public int rnumlob()
            throws CuriaException
Get the number of the large objects stored in the database.

Returns:
the number of the large objects stored in the database.
Throws:
CuriaException - if an error occurs.

setalign

public void setalign(int align)
              throws CuriaException
Set alignment of the database handle.

Parameters:
align - the basic size of alignment.
Throws:
CuriaException - if an error occurs.
Note:
If alignment is set to a database, the efficiency of overwriting values is improved. The size of alignment is suggested to be average size of the values of the records to be stored. If alignment is positive, padding whose size is multiple number of the alignment is placed. If alignment is negative, as `vsiz' is the size of a value, the size of padding is calculated with `(vsiz / pow(2, abs(align) - 1))'. Because alignment setting is not saved in a database, you should specify alignment every opening a database.

setfbpsiz

public void setfbpsiz(int size)
               throws CuriaException
Set the size of the free block pool.

Parameters:
size - the size of the free block pool of a database.
Throws:
CuriaException - if an error occurs.
Note:
The default size of the free block pool is 16. If the size is greater, the space efficiency of overwriting values is improved with the time efficiency sacrificed.

snaffle

public static byte[] snaffle(java.lang.String name,
                             byte[] key)
                      throws CuriaException
Retrieve a record directly from a database directory.

Parameters:
name - the name of a database directory.
key - a byte array of a key.
Throws:
CuriaException - if an error occurs or no record corresponds.
Note:
Although this method can be used even while the database directory is locked by another process, it is not assured that recent updated is reflected.

store

public void store(byte[] key,
                  byte[] val,
                  boolean replace)
           throws CuriaException
Store a record.

Specified by:
store in interface ADBM
Parameters:
key - a byte array of a key.
val - a byte array of a value.
replace - whether the existing value is to be overwritten or not.
Throws:
CuriaException - if an error occurs or replace is cancelled.

sync

public void sync()
          throws CuriaException
Synchronize updating contents with the files and the devices.

Throws:
CuriaException - if an error occurs.
Note:
This method is useful when another process uses the connected database directory.

version

public static java.lang.String version()
Get the version information.

Returns:
a string of the version information.

vsiz

public int vsiz(byte[] key)
         throws CuriaException
Get the size of the value of a record.

Parameters:
key - a byte array of a key.
Returns:
the size of the value of the corresponding record. If the silent flag is true and no record corresponds, -1 is returned instead of exception.
Throws:
CuriaException - if an error occurs or no record corresponds.
Note:
Because this method does not read the entity of a record, it is faster than `get'.

vsizlob

public int vsizlob(byte[] key)
            throws CuriaException
Get the size of the value of a large object.

Parameters:
key - a byte array of a key.
Returns:
the size of the value of the corresponding large object.
Throws:
CuriaException - if an error occurs or no large object corresponds.
Note:
Because this method does not read the entity of a large object, it is faster than `get'.

writable

public boolean writable()
                 throws CuriaException
Check whether the database handle is a writer or not.

Returns:
true if the handle is a writer, false if not.
Throws:
CuriaException - if an error occurs.


qdbm-1.8.78/java/japidoc/qdbm/Villa.html0000644000175000017500000027054611426320065016773 0ustar mikiomikio Villa (qdbm)

qdbm
Class Villa

java.lang.Object
  extended by qdbm.Villa
All Implemented Interfaces:
ADBM

public class Villa
extends java.lang.Object
implements ADBM

The Java API of Villa, the advanced API of QDBM. This class depends on the native library `jqdbm'.


Field Summary
static int CMPDEC
          comparing mode: compare as decimal strings
static int CMPLEX
          comparing mode: compare by lexical order
static int CMPNUM
          comparing mode: compare as long integers
static int CMPOBJ
          comparing mode: compare as comparable objects
static int CPAFTER
          insertion mode: insert after the current record
static int CPBEFORE
          insertion mode: insert before the current record
static int CPCURRENT
          insertion mode: overwrite the current record
static int DCAT
          write mode: concatenate values
static int DDUP
          write mode: allow duplication of records
static int DDUPR
          write mode: allow duplication with reverse order
static int DKEEP
          write mode: keep the existing value
static int DOVER
          write mode: overwrite the existing value
static int EALLOC
          error code: memory allocation error
static int EBROKEN
          error code: broken database file
static int ECLOSE
          error code: close error
static int EFATAL
          error code: with fatal error
static int EKEEP
          error code: existing record
static int ELOCK
          error code: lock error
static int EMAP
          error code: memory mapping error
static int EMISC
          error code: miscellaneous error
static int EMKDIR
          error code: mkdir error
static int EMODE
          error code: invalid mode
static int ENOERR
          error code: no error
static int ENOITEM
          error code: no item found
static int EOPEN
          error code: open error
static int EREAD
          error code: read error
static int ERMDIR
          error code: rmdir error
static int ESEEK
          error code: seek error
static int ESTAT
          error code: stat error
static int ESYNC
          error code: sync error
static int ETRUNC
          error code: trunc error
static int EUNLINK
          error code: unlink error
static int EWRITE
          error code: write error
static int JBACKWARD
          jump mode: jump mode: step backward
static int JFORWARD
          jump mode: jump mode: step forward
static int OCREAT
          open mode: writer creating
static int OLCKNB
          open mode: lock without blocking
static int ONOLCK
          open mode: open without locking
static int OREADER
          open mode: open as a reader
static int OTRUNC
          open mode: writer truncating
static int OWRITER
          open mode: open as a writer
static int OXCOMP
          open mode: compress leaves with BZIP2
static int OYCOMP
          open mode: compress leaves with LZO
static int OZCOMP
          open mode: compress leaves with ZLIB
 boolean silent
          Whether to repress frequent exceptions.
 
Constructor Summary
Villa(java.lang.String name)
          Get the database handle as a reader.
Villa(java.lang.String name, int omode, int cmode)
          Get the database handle.
 
Method Summary
 void close()
          Close the database handle.
 boolean curfirst()
          Move the cursor to the first record.
 boolean curjump(byte[] key)
          Move the cursor to a position around a record for stepping forward.
 boolean curjump(byte[] key, int jmode)
          Move the cursor to a position around a record.
 boolean curjumpobj(java.lang.Object key, int jmode)
          Move the cursor to a position around a record composed of serializable objects.
 byte[] curkey()
          Get the key of the record where the cursor is.
 java.lang.Object curkeyobj()
          Get the key of the record composed of serializable objects, where the cursor is.
 boolean curlast()
          Move the cursor to the last record.
 boolean curnext()
          Move the cursor to the next record.
 boolean curout()
          Delete the record where the cursor is.
 boolean curprev()
          Move the cursor to the next record.
 boolean curput(byte[] val)
          Insert a record as the successor of the cursor.
 boolean curput(byte[] val, int cpmode)
          Insert a record around the cursor.
 boolean curputobj(java.lang.Object val, int cpmode)
          Insert a record around the cursor.
 byte[] curval()
          Get the value of the record where the cursor is.
 java.lang.Object curvalobj()
          Get the value of the record where the cursor is.
 void delete(byte[] key)
          Delete a record.
static java.lang.String errmsg(int ecode)
          Get an error message.
 boolean error()
          Check whether a fatal error occured or not.
 boolean fatalerror()
          Check whether the database has a fatal error or not.
 byte[] fetch(byte[] key)
          Fetch a record.
protected  void finalize()
          Release the resources.
 byte[] firstkey()
          Get the first key.
 int fsiz()
          Get the size of the database file.
 byte[] get(byte[] key)
          Retrieve a record.
 int getindex()
          Get the index of the native table for database handles.
 java.lang.Object getobj(java.lang.Object key)
          Retrieve a record composed of serializable objects.
 int inode()
          Get the inode number of the database.
 int lnum()
          Get the number of the leaf nodes of B+ tree.
 long mtime()
          Get the last modified time of the database.
 VillaCursor mulcuropen()
          Get a multiple cursor.
 java.lang.String name()
          Get the name of the database.
 byte[] nextkey()
          Get the next key.
 int nnum()
          Get the number of the non-leaf nodes of B+ tree.
 void optimize()
          Optimize the database.
 boolean out(byte[] key)
          Delete a record.
 boolean outobj(java.lang.Object key)
          Delete a record composed of serializable objects.
 boolean put(byte[] key, byte[] val)
          Store a record with overwrite.
 boolean put(byte[] key, byte[] val, int dmode)
          Store a record.
 boolean putobj(java.lang.Object key, java.lang.Object val, int dmode)
          Store a record composed of serializable objects.
static void remove(java.lang.String name)
          Remove a database file.
 int rnum()
          Get the number of the records stored in a database.
 void settuning(int lrecmax, int nidxmax, int lcnum, int ncnum)
          Set the tuning parameters for performance.
 void store(byte[] key, byte[] val, boolean replace)
          Store a record.
 void sync()
          Synchronize updating contents with the file and the device.
 void tranabort()
          Abort the transaction.
 void tranbegin()
          Begin the transaction.
 void trancommit()
          Commit the transaction.
static java.lang.String version()
          Get the version information.
 int vnum(byte[] key)
          Get the number of records corresponding a key.
 int vnumobj(java.lang.Object key)
          Get the number of records corresponding a key, composed of serializable objects.
 int vsiz(byte[] key)
          Get the size of the value of a record.
 int vsizobj(java.lang.Object key)
          Get the size of the value of a record, composed of serializable objects.
 boolean writable()
          Check whether the database handle is a writer or not.
 
Methods inherited from class java.lang.Object
clone, equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

CMPDEC

public static final int CMPDEC
comparing mode: compare as decimal strings

See Also:
Constant Field Values

CMPLEX

public static final int CMPLEX
comparing mode: compare by lexical order

See Also:
Constant Field Values

CMPNUM

public static final int CMPNUM
comparing mode: compare as long integers

See Also:
Constant Field Values

CMPOBJ

public static final int CMPOBJ
comparing mode: compare as comparable objects

See Also:
Constant Field Values

CPAFTER

public static final int CPAFTER
insertion mode: insert after the current record

See Also:
Constant Field Values

CPBEFORE

public static final int CPBEFORE
insertion mode: insert before the current record

See Also:
Constant Field Values

CPCURRENT

public static final int CPCURRENT
insertion mode: overwrite the current record

See Also:
Constant Field Values

DCAT

public static final int DCAT
write mode: concatenate values

See Also:
Constant Field Values

DDUP

public static final int DDUP
write mode: allow duplication of records

See Also:
Constant Field Values

DDUPR

public static final int DDUPR
write mode: allow duplication with reverse order

See Also:
Constant Field Values

DKEEP

public static final int DKEEP
write mode: keep the existing value

See Also:
Constant Field Values

DOVER

public static final int DOVER
write mode: overwrite the existing value

See Also:
Constant Field Values

EALLOC

public static final int EALLOC
error code: memory allocation error

See Also:
Constant Field Values

EBROKEN

public static final int EBROKEN
error code: broken database file

See Also:
Constant Field Values

ECLOSE

public static final int ECLOSE
error code: close error

See Also:
Constant Field Values

EFATAL

public static final int EFATAL
error code: with fatal error

See Also:
Constant Field Values

EKEEP

public static final int EKEEP
error code: existing record

See Also:
Constant Field Values

ELOCK

public static final int ELOCK
error code: lock error

See Also:
Constant Field Values

EMAP

public static final int EMAP
error code: memory mapping error

See Also:
Constant Field Values

EMISC

public static final int EMISC
error code: miscellaneous error

See Also:
Constant Field Values

EMKDIR

public static final int EMKDIR
error code: mkdir error

See Also:
Constant Field Values

EMODE

public static final int EMODE
error code: invalid mode

See Also:
Constant Field Values

ENOERR

public static final int ENOERR
error code: no error

See Also:
Constant Field Values

ENOITEM

public static final int ENOITEM
error code: no item found

See Also:
Constant Field Values

EOPEN

public static final int EOPEN
error code: open error

See Also:
Constant Field Values

EREAD

public static final int EREAD
error code: read error

See Also:
Constant Field Values

ERMDIR

public static final int ERMDIR
error code: rmdir error

See Also:
Constant Field Values

ESEEK

public static final int ESEEK
error code: seek error

See Also:
Constant Field Values

ESTAT

public static final int ESTAT
error code: stat error

See Also:
Constant Field Values

ESYNC

public static final int ESYNC
error code: sync error

See Also:
Constant Field Values

ETRUNC

public static final int ETRUNC
error code: trunc error

See Also:
Constant Field Values

EUNLINK

public static final int EUNLINK
error code: unlink error

See Also:
Constant Field Values

EWRITE

public static final int EWRITE
error code: write error

See Also:
Constant Field Values

JBACKWARD

public static final int JBACKWARD
jump mode: jump mode: step backward

See Also:
Constant Field Values

JFORWARD

public static final int JFORWARD
jump mode: jump mode: step forward

See Also:
Constant Field Values

OCREAT

public static final int OCREAT
open mode: writer creating

See Also:
Constant Field Values

OLCKNB

public static final int OLCKNB
open mode: lock without blocking

See Also:
Constant Field Values

ONOLCK

public static final int ONOLCK
open mode: open without locking

See Also:
Constant Field Values

OREADER

public static final int OREADER
open mode: open as a reader

See Also:
Constant Field Values

OTRUNC

public static final int OTRUNC
open mode: writer truncating

See Also:
Constant Field Values

OWRITER

public static final int OWRITER
open mode: open as a writer

See Also:
Constant Field Values

OXCOMP

public static final int OXCOMP
open mode: compress leaves with BZIP2

See Also:
Constant Field Values

OYCOMP

public static final int OYCOMP
open mode: compress leaves with LZO

See Also:
Constant Field Values

OZCOMP

public static final int OZCOMP
open mode: compress leaves with ZLIB

See Also:
Constant Field Values

silent

public boolean silent
Whether to repress frequent exceptions.

Constructor Detail

Villa

public Villa(java.lang.String name)
      throws VillaException
Get the database handle as a reader. The same as `Villa(name, Villa.OREADER, Villa.CMPLEX)'.

Throws:
VillaException
See Also:
Villa(java.lang.String, int, int)

Villa

public Villa(java.lang.String name,
             int omode,
             int cmode)
      throws VillaException
Get the database handle.

Parameters:
name - the name of a database file.
omode - the connection mode: `Villa.OWRITER' as a writer, `Villa.OREADER' as a reader. If the mode is `Villa.OWRITER', the following may be added by bitwise or: `Villa.OCREAT', which means it creates a new database if not exist, `Villa.OTRUNC', which means it creates a new database regardless if one exists, `Villa.OZCOMP', which means leaves in the database are compressed with ZLIB, `Villa.OYCOMP', which means leaves in the database are compressed with LZO, `Villa.OXCOMP', which means leaves in the database are compressed with BZIP2. Both of `Villa.OREADER' and `Villa.OWRITER' can be added to by bitwise or: `Villa.ONOLCK', which means it opens a database file without file locking, or `Villa.OLCKNB', which means locking is performed without blocking.
cmode - the comparing function: `Villa.CMPLEX' comparing keys in lexical order, `Villa.CMPNUM' comparing keys as numbers of big endian, `Villa.CMPDEC' comparing keys as decimal strings, `Villa.CMPOBJ' comparing keys as serialized objects implementing `java.util.Comparable'. The comparing function should be kept same in the life of a database.
Throws:
VillaException
Note:
While connecting as a writer, an exclusive lock is invoked to the database file. While connecting as a reader, a shared lock is invoked to the database file. The thread blocks until the lock is achieved. `Villa.OZCOMP', `Villa.OYCOMP', and `Villa.OXCOMP' are available only if QDBM was built each with ZLIB, LZO, and BZIP2 enabled. If `Villa.ONOLCK' is used, the application is responsible for exclusion control.
Method Detail

close

public void close()
           throws VillaException
Close the database handle.

Specified by:
close in interface ADBM
Throws:
VillaException - if an error occurs.
Note:
Updating a database is assured to be written when the handle is closed. If a writer opens a database but does not close it appropriately, the database will be broken. If the transaction is activated and not committed, it is aborted.

curfirst

public boolean curfirst()
                 throws VillaException
Move the cursor to the first record.

Returns:
always true. However, if the silent flag is true and no record corresponds, false is returned instead of exception.
Throws:
VillaException - if an error occurs or there is no record in the database.

curjump

public boolean curjump(byte[] key)
                throws VillaException
Move the cursor to a position around a record for stepping forward. The same as `curjump(key, Villa.JFORFARD)'.

Throws:
VillaException
See Also:
curjump(byte[], int)

curjump

public boolean curjump(byte[] key,
                       int jmode)
                throws VillaException
Move the cursor to a position around a record.

Parameters:
key - a byte array of a key.
jmode - detail adjustment: `Villa.JFORWARD', which means that the cursor is set to the first record of the same key and that the cursor is set to the next substitute if completely matching record does not exist, `Villa.JBACKWARD', which means that the cursor is set to the last record of the same key and that the cursor is set to the previous substitute if completely matching record does not exist.
Returns:
always true. However, if the silent flag is true and no record corresponds, false is returned instead of exception.
Throws:
VillaException - if an error occurs or there is no record corresponding the condition.

curjumpobj

public boolean curjumpobj(java.lang.Object key,
                          int jmode)
                   throws VillaException
Move the cursor to a position around a record composed of serializable objects. The same as `curjump(qdbm.Util.serialize(key), jmode)'.

Throws:
VillaException
See Also:
curjump(byte[], int)
Note:
If serialization is failed, an instance of `VillaException' is thrown.

curkey

public byte[] curkey()
              throws VillaException
Get the key of the record where the cursor is.

Returns:
a byte array of the key of the corresponding record. If the silent flag is true and no record corresponds, `null' is returned instead of exception.
Throws:
VillaException - if an error occurs or no record corresponds to the cursor.

curkeyobj

public java.lang.Object curkeyobj()
                           throws VillaException
Get the key of the record composed of serializable objects, where the cursor is. The same as `qdbm.Util.deserialize(curkey())'.

Throws:
VillaException
See Also:
curkey()
Note:
If serialization is failed, an instance of `VillaException' is thrown.

curlast

public boolean curlast()
                throws VillaException
Move the cursor to the last record.

Returns:
always true. However, if the silent flag is true and no record corresponds, false is returned instead of exception.
Throws:
VillaException - if an error occurs or there is no record in the database.

curnext

public boolean curnext()
                throws VillaException
Move the cursor to the next record.

Returns:
always true. However, if the silent flag is true and no record corresponds, false is returned instead of exception.
Throws:
VillaException - if an error occurs or there is no next record.

curout

public boolean curout()
               throws VillaException
Delete the record where the cursor is.

Returns:
always true. However, if the silent flag is true and no record corresponds to the cursor, false is returned instead of exception.
Throws:
VillaException - if an error occurs or no record corresponds to the cursor.
Note:
After deletion, the cursor is moved to the next record if possible.

curprev

public boolean curprev()
                throws VillaException
Move the cursor to the next record.

Returns:
always true. However, if the silent flag is true and no record corresponds, false is returned instead of exception.
Throws:
VillaException - if an error occurs or there is no previous record.

curput

public boolean curput(byte[] val)
               throws VillaException
Insert a record as the successor of the cursor. The same as `curput(val, Villa.CPCURRENT)'.

Throws:
VillaException
See Also:
curput(byte[], int)

curput

public boolean curput(byte[] val,
                      int cpmode)
               throws VillaException
Insert a record around the cursor.

Parameters:
val - a byte array of a value.
cpmode - detail adjustment: `Villa.CPCURRENT', which means that the value of the current record is overwritten, `Villa.CPBEFORE', which means that a new record is inserted before the current record, `Villa.CPAFTER', which means that a new record is inserted after the current record.
Returns:
always true. However, if the silent flag is true and no record corresponds to the cursor, false is returned instead of exception.
Throws:
VillaException - if an error occurs or no record corresponds to the cursor.
Note:
After insertion, the cursor is moved to the inserted record.

curputobj

public boolean curputobj(java.lang.Object val,
                         int cpmode)
                  throws VillaException
Insert a record around the cursor. The same as `curput(qdbm.Util.serialize(val), cpmode)'.

Throws:
VillaException
See Also:
curput(byte[], int)

curval

public byte[] curval()
              throws VillaException
Get the value of the record where the cursor is.

Returns:
a byte array of the value of the corresponding record. If the silent flag is true and no record corresponds, `null' is returned instead of exception.
Throws:
VillaException - if an error occurs or no record corresponds to the cursor.

curvalobj

public java.lang.Object curvalobj()
                           throws VillaException
Get the value of the record where the cursor is. The same as `qdbm.Util.deserialize(curval())'.

Throws:
VillaException
See Also:
curval()
Note:
If serialization is failed, an instance of `VillaException' is thrown.

delete

public void delete(byte[] key)
            throws VillaException
Delete a record.

Specified by:
delete in interface ADBM
Parameters:
key - a byte array of a key.
Throws:
VillaException - if an error occurs or no record corresponds.

errmsg

public static java.lang.String errmsg(int ecode)
Get an error message.

Parameters:
ecode - an error code.
Returns:
the message string of the error code.

error

public boolean error()
              throws VillaException
Check whether a fatal error occured or not.

Specified by:
error in interface ADBM
Returns:
true if the database has a fatal error, false if not.
Throws:
VillaException - if an error occurs.

fatalerror

public boolean fatalerror()
                   throws VillaException
Check whether the database has a fatal error or not.

Returns:
true if the database has a fatal error, false if not.
Throws:
VillaException - if an error occurs.

fetch

public byte[] fetch(byte[] key)
             throws VillaException
Fetch a record.

Specified by:
fetch in interface ADBM
Parameters:
key - a byte array of a key.
Returns:
a byte array of the value of the corresponding record.
Throws:
VillaException - if an error occurs or no record corresponds.

finalize

protected void finalize()
                 throws java.lang.Throwable
Release the resources.

Overrides:
finalize in class java.lang.Object
Throws:
java.lang.Throwable
Note:
If the database handle is not closed yet, it is closed. Every database should be closed explicitly. Do not cast the duty on the gerbage collection.

firstkey

public byte[] firstkey()
                throws VillaException
Get the first key.

Specified by:
firstkey in interface ADBM
Returns:
a byte array of the key of the first record.
Throws:
VillaException - if an error occurs or no record corresponds.

fsiz

public int fsiz()
         throws VillaException
Get the size of the database file.

Returns:
the size of the database file.
Throws:
VillaException - if an error occurs.
Note:
Because of the I/O buffer, the return value may be less than the real size.

get

public byte[] get(byte[] key)
           throws VillaException
Retrieve a record.

Parameters:
key - a byte array of a key.
Returns:
a byte array of the value of the corresponding record. If the silent flag is true and no record corresponds, `null' is returned instead of exception.
Throws:
VillaException - if an error occurs, no record corresponds.
Note:
When the key of duplicated records is specified, the value of the first record of the same key is selected.

getindex

public int getindex()
Get the index of the native table for database handles.

Returns:
the index of the native table for database handles.

getobj

public java.lang.Object getobj(java.lang.Object key)
                        throws VillaException
Retrieve a record composed of serializable objects. The same as `qdbm.Util.deserialize(get(qdbm.Util.serialize(key)))'.

Throws:
VillaException
See Also:
get(byte[])
Note:
If serialization is failed, an instance of `VillaException' is thrown.

inode

public int inode()
          throws VillaException
Get the inode number of the database.

Returns:
the inode number of the database file.
Throws:
VillaException - if an error occurs.

lnum

public int lnum()
         throws VillaException
Get the number of the leaf nodes of B+ tree.

Returns:
the number of the leaf nodes.
Throws:
VillaException - if an error occurs.

mtime

public long mtime()
           throws VillaException
Get the last modified time of the database.

Returns:
the last modified time of the database.
Throws:
VillaException - if an error occurs.

mulcuropen

public VillaCursor mulcuropen()
                       throws VillaException
Get a multiple cursor.

Returns:
a multiple cursor.
Throws:
VillaException
Note:
Even if plural cursors are fetched out of a database handle, they does not share the locations with each other. Note that this method can be used only if the database handle is connected as a reader.

name

public java.lang.String name()
                      throws VillaException
Get the name of the database.

Returns:
the string of the name of the database.
Throws:
VillaException - if an error occurs.

nextkey

public byte[] nextkey()
               throws VillaException
Get the next key.

Specified by:
nextkey in interface ADBM
Returns:
a byte array of the key of the next record.
Throws:
VillaException - if an error occurs or no record corresponds.

nnum

public int nnum()
         throws VillaException
Get the number of the non-leaf nodes of B+ tree.

Returns:
the number of the non-leaf nodes.
Throws:
VillaException - if an error occurs.

optimize

public void optimize()
              throws VillaException
Optimize the database.

Throws:
VillaException - if an error occurs.
Note:
In an alternating succession of deleting and storing with overwrite or concatenate, dispensable regions accumulate. This method is useful to do away with them. This method should not be used while the transaction is activated.

out

public boolean out(byte[] key)
            throws VillaException
Delete a record.

Parameters:
key - a byte array of a key.
Returns:
always true. However, if the silent flag is true and no record corresponds, false is returned instead of exception.
Throws:
VillaException - if an error occurs or no record corresponds.
Note:
When the key of duplicated records is specified, the first record of the same key is deleted. The cursor becomes unavailable due to updating database.

outobj

public boolean outobj(java.lang.Object key)
               throws VillaException
Delete a record composed of serializable objects. The same as `out(qdbm.Util.serialize(key))'.

Throws:
VillaException
See Also:
out(byte[])
Note:
If serialization is failed, an instance of `VillaException' is thrown.

put

public boolean put(byte[] key,
                   byte[] val)
            throws VillaException
Store a record with overwrite. The same as `put(key, val, Villa.DOVER)'.

Throws:
VillaException
See Also:
put(byte[], byte[], int)

put

public boolean put(byte[] key,
                   byte[] val,
                   int dmode)
            throws VillaException
Store a record.

Parameters:
key - a byte array of a key.
val - a byte array of a value.
dmode - behavior when the key overlaps, by the following values: `Villa.DOVER', which means the specified value overwrites the existing one, `Villa.DKEEP', which means the existing value is kept, `Villa.DCAT', which means the specified value is concatenated at the end of the existing value, `Villa.DDUP', which means duplication of keys is allowed and the specified value is added as the last one, `Villa.DDUPR', which means duplication of keys is allowed and the specified value is added as the first one.
Returns:
always true. However, if the silent flag is true and replace is cancelled, false is returned instead of exception.
Throws:
VillaException - if an error occurs or replace is cancelled.
Note:
The cursor becomes unavailable due to updating database.

putobj

public boolean putobj(java.lang.Object key,
                      java.lang.Object val,
                      int dmode)
               throws VillaException
Store a record composed of serializable objects. The same as `put(qdbm.Util.serialize(key), qdbm.Util.serialize(val), dmode)'.

Throws:
VillaException
See Also:
put(byte[], byte[], int)
Note:
If serialization is failed, an instance of `VillaException' is thrown.

remove

public static void remove(java.lang.String name)
                   throws VillaException
Remove a database file.

Parameters:
name - the name of a database file.
Throws:
VillaException - if an error occurs.

rnum

public int rnum()
         throws VillaException
Get the number of the records stored in a database.

Returns:
the number of the records stored in the database.
Throws:
VillaException - if an error occurs.

settuning

public void settuning(int lrecmax,
                      int nidxmax,
                      int lcnum,
                      int ncnum)
               throws VillaException
Set the tuning parameters for performance.

Parameters:
lrecmax - the max number of records in a leaf node of B+ tree. If it is not more than 0, the default value is specified.
nidxmax - the max number of indexes in a non-leaf node of B+ tree. If it is not more than 0, the default value is specified.
lcnum - the max number of caching leaf nodes. If it is not more than 0, the default value is specified.
ncnum - the max number of caching non-leaf nodes. If it is not more than 0, the default value is specified.
Throws:
VillaException - if an error occurs.
Note:
The default setting is equivalent to `settuning(49, 192, 1024, 512)'. Because tuning parameters are not saved in a database, you should specify them every opening a database.

store

public void store(byte[] key,
                  byte[] val,
                  boolean replace)
           throws VillaException
Store a record.

Specified by:
store in interface ADBM
Parameters:
key - a byte array of a key.
val - a byte array of a value.
replace - whether the existing value is to be overwritten or not.
Throws:
VillaException - if an error occurs or replace is cancelled.

sync

public void sync()
          throws VillaException
Synchronize updating contents with the file and the device.

Throws:
VillaException - if an error occurs.
Note:
This method is useful when another process uses the connected database file. This method should not be used while the transaction is activated.

tranabort

public void tranabort()
               throws VillaException
Abort the transaction.

Throws:
VillaException - if an error occurs.
Note:
Updating a database in the transaction is discarded when it is aborted. The state of the database is rollbacked to before transaction. Any other thread except for the one which began the transaction should not call this method.

tranbegin

public void tranbegin()
               throws VillaException
Begin the transaction.

Throws:
VillaException - if an error occurs.
Note:
If a thread is already in the transaction, the other threads block until the prius is out of the transaction. Only one transaction can be activated with a database handle at the same time.

trancommit

public void trancommit()
                throws VillaException
Commit the transaction.

Throws:
VillaException - if an error occurs.
Note:
Updating a database in the transaction is fixed when it is committed successfully. Any other thread except for the one which began the transaction should not call this method.

version

public static java.lang.String version()
Get the version information.

Returns:
the string of the version information.

vnum

public int vnum(byte[] key)
         throws VillaException
Get the number of records corresponding a key.

Parameters:
key - a byte array of a key.
Returns:
the number of corresponding records. If no record corresponds, 0 is returned.
Throws:
VillaException - if an error occurs.

vnumobj

public int vnumobj(java.lang.Object key)
            throws VillaException
Get the number of records corresponding a key, composed of serializable objects. The same as `vnum(qdbm.Util.serialize(key))'.

Throws:
VillaException
See Also:
vnum(byte[])
Note:
If serialization is failed, an instance of `VillaException' is thrown.

vsiz

public int vsiz(byte[] key)
         throws VillaException
Get the size of the value of a record.

Parameters:
key - a byte array of a key.
Returns:
the size of the value of the corresponding record. If multiple records correspond, the size of the first is returned. If the silent flag is true and no record corresponds, -1 is returned instead of exception.
Throws:
VillaException - if an error occurs.

vsizobj

public int vsizobj(java.lang.Object key)
            throws VillaException
Get the size of the value of a record, composed of serializable objects. The same as `vsiz(qdbm.Util.serialize(key))'.

Throws:
VillaException
See Also:
vnum(byte[])
Note:
If serialization is failed, an instance of `VillaException' is thrown.

writable

public boolean writable()
                 throws VillaException
Check whether the database handle is a writer or not.

Returns:
true if the handle is a writer, false if not.
Throws:
VillaException - if an error occurs.


qdbm-1.8.78/java/japidoc/qdbm/CuriaException.html0000644000175000017500000002450011426320065020631 0ustar mikiomikio CuriaException (qdbm)

qdbm
Class CuriaException

java.lang.Object
  extended by java.lang.Throwable
      extended by java.lang.Exception
          extended by qdbm.DBMException
              extended by qdbm.CuriaException
All Implemented Interfaces:
java.io.Serializable

public class CuriaException
extends DBMException

Exception container of Curia.

See Also:
Serialized Form

Field Summary
 int ecode
          error code
 
Constructor Summary
CuriaException()
          Set the error code with `Curia.EMISC'.
CuriaException(int ecode)
          Set the error code.
 
Method Summary
 
Methods inherited from class java.lang.Throwable
fillInStackTrace, getCause, getLocalizedMessage, getMessage, getStackTrace, initCause, printStackTrace, printStackTrace, printStackTrace, setStackTrace, toString
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
 

Field Detail

ecode

public final int ecode
error code

Constructor Detail

CuriaException

public CuriaException()
Set the error code with `Curia.EMISC'.


CuriaException

public CuriaException(int ecode)
Set the error code.

Parameters:
ecode - an error code.


qdbm-1.8.78/java/japidoc/qdbm/Depot.html0000644000175000017500000017372311426320065016776 0ustar mikiomikio Depot (qdbm)

qdbm
Class Depot

java.lang.Object
  extended by qdbm.Depot
All Implemented Interfaces:
ADBM

public class Depot
extends java.lang.Object
implements ADBM

The Java API of Depot, the basic API of QDBM. This class depends on the native library `jqdbm'.


Field Summary
static int DCAT
          write mode: concatenate values
static int DKEEP
          write mode: keep the existing value
static int DOVER
          write mode: overwrite the existing value
static int EALLOC
          error code: memory allocation error
static int EBROKEN
          error code: broken database file
static int ECLOSE
          error code: close error
static int EFATAL
          error code: with fatal error
static int EKEEP
          error code: existing record
static int ELOCK
          error code: lock error
static int EMAP
          error code: memory mapping error
static int EMISC
          error code: miscellaneous error
static int EMKDIR
          error code: mkdir error
static int EMODE
          error code: invalid mode
static int ENOERR
          error code: no error
static int ENOITEM
          error code: no item found
static int EOPEN
          error code: open error
static int EREAD
          error code: read error
static int ERMDIR
          error code: rmdir error
static int ESEEK
          error code: seek error
static int ESTAT
          error code: stat error
static int ESYNC
          error code: sync error
static int ETRUNC
          error code: trunc error
static int EUNLINK
          error code: unlink error
static int EWRITE
          error code: write error
static int OCREAT
          open mode: writer creating
static int OLCKNB
          open mode: lock without blocking
static int ONOLCK
          open mode: open without locking
static int OREADER
          open mode: open as a reader
static int OSPARSE
          open mode: create as a sparse file
static int OTRUNC
          open mode: writer truncating
static int OWRITER
          open mode: open as a writer
 boolean silent
          Whether to repress frequent exceptions.
 
Constructor Summary
Depot(java.lang.String name)
          Get the database handle as a reader.
Depot(java.lang.String name, int omode, int bnum)
          Get the database handle.
 
Method Summary
 int bnum()
          Get the number of the elements of the bucket array.
 int busenum()
          Get the number of the used elements of the bucket array.
 void close()
          Close the database handle.
 void delete(byte[] key)
          Delete a record.
static java.lang.String errmsg(int ecode)
          Get an error message.
 boolean error()
          Check whether a fatal error occured or not.
 boolean fatalerror()
          Check whether the database has a fatal error or not.
 byte[] fetch(byte[] key)
          Fetch a record.
protected  void finalize()
          Release the resources.
 byte[] firstkey()
          Get the first key.
 int fsiz()
          Get the size of the database file.
 byte[] get(byte[] key)
          Retrieve whole value of a record.
 byte[] get(byte[] key, int start, int max)
          Retrieve a record.
 int inode()
          Get the inode number of the database.
 void iterinit()
          Initialize the iterator of the database handle.
 byte[] iternext()
          Get the next key of the iterator.
 long mtime()
          Get the last modified time of the database.
 java.lang.String name()
          Get the name of the database.
 byte[] nextkey()
          Get the next key.
 void optimize(int bnum)
          Optimize the database.
 boolean out(byte[] key)
          Delete a record.
 boolean put(byte[] key, byte[] val)
          Store a record with overwrite.
 boolean put(byte[] key, byte[] val, int dmode)
          Store a record.
static void remove(java.lang.String name)
          Remove a database file.
 int rnum()
          Get the number of the records stored in the database.
 void setalign(int align)
          Set alignment of the database handle.
 void setfbpsiz(int size)
          Set the size of the free block pool.
static byte[] snaffle(java.lang.String name, byte[] key)
          Retrieve a record directly from a database file.
 void store(byte[] key, byte[] val, boolean replace)
          Store a record.
 void sync()
          Synchronize updating contents with the file and the device.
static java.lang.String version()
          Get the version information.
 int vsiz(byte[] key)
          Get the size of the value of a record.
 boolean writable()
          Check whether the database handle is a writer or not.
 
Methods inherited from class java.lang.Object
clone, equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

DCAT

public static final int DCAT
write mode: concatenate values

See Also:
Constant Field Values

DKEEP

public static final int DKEEP
write mode: keep the existing value

See Also:
Constant Field Values

DOVER

public static final int DOVER
write mode: overwrite the existing value

See Also:
Constant Field Values

EALLOC

public static final int EALLOC
error code: memory allocation error

See Also:
Constant Field Values

EBROKEN

public static final int EBROKEN
error code: broken database file

See Also:
Constant Field Values

ECLOSE

public static final int ECLOSE
error code: close error

See Also:
Constant Field Values

EFATAL

public static final int EFATAL
error code: with fatal error

See Also:
Constant Field Values

EKEEP

public static final int EKEEP
error code: existing record

See Also:
Constant Field Values

ELOCK

public static final int ELOCK
error code: lock error

See Also:
Constant Field Values

EMAP

public static final int EMAP
error code: memory mapping error

See Also:
Constant Field Values

EMISC

public static final int EMISC
error code: miscellaneous error

See Also:
Constant Field Values

EMKDIR

public static final int EMKDIR
error code: mkdir error

See Also:
Constant Field Values

EMODE

public static final int EMODE
error code: invalid mode

See Also:
Constant Field Values

ENOERR

public static final int ENOERR
error code: no error

See Also:
Constant Field Values

ENOITEM

public static final int ENOITEM
error code: no item found

See Also:
Constant Field Values

EOPEN

public static final int EOPEN
error code: open error

See Also:
Constant Field Values

EREAD

public static final int EREAD
error code: read error

See Also:
Constant Field Values

ERMDIR

public static final int ERMDIR
error code: rmdir error

See Also:
Constant Field Values

ESEEK

public static final int ESEEK
error code: seek error

See Also:
Constant Field Values

ESTAT

public static final int ESTAT
error code: stat error

See Also:
Constant Field Values

ESYNC

public static final int ESYNC
error code: sync error

See Also:
Constant Field Values

ETRUNC

public static final int ETRUNC
error code: trunc error

See Also:
Constant Field Values

EUNLINK

public static final int EUNLINK
error code: unlink error

See Also:
Constant Field Values

EWRITE

public static final int EWRITE
error code: write error

See Also:
Constant Field Values

OCREAT

public static final int OCREAT
open mode: writer creating

See Also:
Constant Field Values

OLCKNB

public static final int OLCKNB
open mode: lock without blocking

See Also:
Constant Field Values

ONOLCK

public static final int ONOLCK
open mode: open without locking

See Also:
Constant Field Values

OREADER

public static final int OREADER
open mode: open as a reader

See Also:
Constant Field Values

OSPARSE

public static final int OSPARSE
open mode: create as a sparse file

See Also:
Constant Field Values

OTRUNC

public static final int OTRUNC
open mode: writer truncating

See Also:
Constant Field Values

OWRITER

public static final int OWRITER
open mode: open as a writer

See Also:
Constant Field Values

silent

public boolean silent
Whether to repress frequent exceptions.

Constructor Detail

Depot

public Depot(java.lang.String name)
      throws DepotException
Get the database handle as a reader. The same as `Depot(name, Depot.OREADER, -1)'.

Throws:
DepotException
See Also:
Depot(java.lang.String, int, int)

Depot

public Depot(java.lang.String name,
             int omode,
             int bnum)
      throws DepotException
Get the database handle.

Parameters:
name - the name of a database file.
omode - the connection mode: `Depot.OWRITER' as a writer, `Depot.OREADER' as a reader. If the mode is `Depot.OWRITER', the following may be added by bitwise or: `Depot.OCREAT', which means it creates a new database if not exist, `Depot.OTRUNC', which means it creates a new database regardless if one exists. Both of `Depot.OREADER' and `Depot.OWRITER' can be added to by bitwise or: `Depot.ONOLCK', which means it opens a database file without file locking, or `Depot.OLCKNB', which means locking is performed without blocking. `Depot.OCREAT' can be added to by bitwise or: `Depot.OSPARSE', which means it creates a database file as a sparse file.
bnum - the number of elements of the bucket array. If it is not more than 0, the default value is specified. The size of a bucket array is determined on creating, and can not be changed except for by optimization of the database. Suggested size of a bucket array is about from 0.5 to 4 times of the number of all records to store.
Throws:
DepotException - if an error occurs.
Note:
While connecting as a writer, an exclusive lock is invoked to the database file. While connecting as a reader, a shared lock is invoked to the database file. The thread blocks until the lock is achieved. If `Depot.ONOLCK' is used, the application is responsible for exclusion control.
Method Detail

bnum

public int bnum()
         throws DepotException
Get the number of the elements of the bucket array.

Returns:
the number of the elements of the bucket array.
Throws:
DepotException - if an error occurs.

busenum

public int busenum()
            throws DepotException
Get the number of the used elements of the bucket array.

Returns:
the number of the used elements of the bucket array.
Throws:
DepotException - if an error occurs.
Note:
This method is inefficient because it accesses all elements of the bucket array.

close

public void close()
           throws DepotException
Close the database handle.

Specified by:
close in interface ADBM
Throws:
DepotException - if an error occurs.
Note:
Updating a database is assured to be written when the handle is closed. If a writer opens a database but does not close it appropriately, the database will be broken.

delete

public void delete(byte[] key)
            throws DepotException
Delete a record.

Specified by:
delete in interface ADBM
Parameters:
key - a byte array of a key.
Throws:
DepotException - if an error occurs or no record corresponds.

errmsg

public static java.lang.String errmsg(int ecode)
Get an error message.

Parameters:
ecode - an error code.
Returns:
the message string of the error code.

error

public boolean error()
              throws DepotException
Check whether a fatal error occured or not.

Specified by:
error in interface ADBM
Returns:
true if the database has a fatal error, false if not.
Throws:
DepotException - if an error occurs.

fatalerror

public boolean fatalerror()
                   throws DepotException
Check whether the database has a fatal error or not.

Returns:
true if the database has a fatal error, false if not.
Throws:
DepotException - if an error occurs.

fetch

public byte[] fetch(byte[] key)
             throws DepotException
Fetch a record.

Specified by:
fetch in interface ADBM
Parameters:
key - a byte array of a key.
Returns:
a byte array of the value of the corresponding record.
Throws:
DepotException - if an error occurs or no record corresponds.

finalize

protected void finalize()
                 throws java.lang.Throwable
Release the resources.

Overrides:
finalize in class java.lang.Object
Throws:
java.lang.Throwable
Note:
If the database handle is not closed yet, it is closed. Every database should be closed explicitly. Do not cast the duty on the gerbage collection.

firstkey

public byte[] firstkey()
                throws DepotException
Get the first key.

Specified by:
firstkey in interface ADBM
Returns:
a byte array of the key of the first record.
Throws:
DepotException - if an error occurs or no record corresponds.

fsiz

public int fsiz()
         throws DepotException
Get the size of the database file.

Returns:
the size of the database file.
Throws:
DepotException - if an error occurs.

get

public byte[] get(byte[] key)
           throws DepotException
Retrieve whole value of a record. The same as `get(key, 0, -1)'.

Throws:
DepotException
See Also:
get(byte[], int, int)

get

public byte[] get(byte[] key,
                  int start,
                  int max)
           throws DepotException
Retrieve a record.

Parameters:
key - a byte array of a key.
start - the array index of the beginning of the value to be read.
max - the max size to read with. If it is negative, the size is unlimited.
Returns:
a byte array of the value of the corresponding record. If the silent flag is true and no record corresponds, `null' is returned instead of exception.
Throws:
DepotException - if an error occurs, no record corresponds, or the size of the value of the corresponding record is less than the index specified by the parameter `start'.

inode

public int inode()
          throws DepotException
Get the inode number of the database.

Returns:
the inode number of the database file.
Throws:
DepotException - if an error occurs.

iterinit

public void iterinit()
              throws DepotException
Initialize the iterator of the database handle.

Throws:
DepotException - if an error occurs.
Note:
The iterator is used in order to access the key of every record stored in a database.

iternext

public byte[] iternext()
                throws DepotException
Get the next key of the iterator.

Returns:
a byte array of the key of the next record. If the silent flag is true and no record corresponds, `null' is returned instead of exception.
Throws:
DepotException - if an error occurs or no record corresponds.
Note:
It is possible to access every record by iteration of calling this method. However, it is not assured if updating the database is occurred while the iteration. Besides, the order of this traversal access method is arbitrary, so it is not assured that the order of storing matches the one of the traversal access.

mtime

public long mtime()
           throws DepotException
Get the last modified time of the database.

Returns:
the last modified time of the database.
Throws:
DepotException - if an error occurs.

name

public java.lang.String name()
                      throws DepotException
Get the name of the database.

Returns:
the string of the name of the database.
Throws:
DepotException - if an error occurs.

nextkey

public byte[] nextkey()
               throws DepotException
Get the next key.

Specified by:
nextkey in interface ADBM
Returns:
a byte array of the key of the next record.
Throws:
DepotException - if an error occurs or no record corresponds.

optimize

public void optimize(int bnum)
              throws DepotException
Optimize the database.

Parameters:
bnum - the number of the elements of the bucket array. If it is not more than 0, the default value is specified.
Throws:
DepotException - if an error occurs.
Note:
In an alternating succession of deleting and storing with overwrite or concatenate, dispensable regions accumulate. This method is useful to do away with them.

out

public boolean out(byte[] key)
            throws DepotException
Delete a record.

Parameters:
key - a byte array of a key.
Returns:
always true. However, if the silent flag is true and no record corresponds, false is returned instead of exception.
Throws:
DepotException - if an error occurs or no record corresponds.

put

public boolean put(byte[] key,
                   byte[] val)
            throws DepotException
Store a record with overwrite. The same as `put(key, val, Depot.DOVER)'.

Throws:
DepotException
See Also:
put(byte[], byte[], int)

put

public boolean put(byte[] key,
                   byte[] val,
                   int dmode)
            throws DepotException
Store a record.

Parameters:
key - a byte array of a key.
val - a byte array of a value.
dmode - behavior when the key overlaps, by the following values: `Depot.DOVER', which means the specified value overwrites the existing one, `Depot.DKEEP', which means the existing value is kept, `Depot.DCAT', which means the specified value is concatenated at the end of the existing value.
Returns:
always true. However, if the silent flag is true and replace is cancelled, false is returned instead of exception.
Throws:
DepotException - if an error occurs or replace is cancelled.

remove

public static void remove(java.lang.String name)
                   throws DepotException
Remove a database file.

Parameters:
name - the name of a database file.
Throws:
DepotException - if an error occurs.

rnum

public int rnum()
         throws DepotException
Get the number of the records stored in the database.

Returns:
the number of the records stored in the database.
Throws:
DepotException - if an error occurs.

setalign

public void setalign(int align)
              throws DepotException
Set alignment of the database handle.

Parameters:
align - the basic size of alignment.
Throws:
DepotException - if an error occurs.
Note:
If alignment is set to a database, the efficiency of overwriting values is improved. The size of alignment is suggested to be average size of the values of the records to be stored. If alignment is positive, padding whose size is multiple number of the alignment is placed. If alignment is negative, as `vsiz' is the size of a value, the size of padding is calculated with `(vsiz / pow(2, abs(align) - 1))'. Because alignment setting is not saved in a database, you should specify alignment every opening a database.

setfbpsiz

public void setfbpsiz(int size)
               throws DepotException
Set the size of the free block pool.

Parameters:
size - the size of the free block pool of a database.
Throws:
DepotException - if an error occurs.
Note:
The default size of the free block pool is 16. If the size is greater, the space efficiency of overwriting values is improved with the time efficiency sacrificed.

snaffle

public static byte[] snaffle(java.lang.String name,
                             byte[] key)
                      throws DepotException
Retrieve a record directly from a database file.

Parameters:
name - the name of a database file.
key - a byte array of a key.
Throws:
DepotException - if an error occurs or no record corresponds.
Note:
Although this method can be used even while the database file is locked by another process, it is not assured that recent updated is reflected.

store

public void store(byte[] key,
                  byte[] val,
                  boolean replace)
           throws DepotException
Store a record.

Specified by:
store in interface ADBM
Parameters:
key - a byte array of a key.
val - a byte array of a value.
replace - whether the existing value is to be overwritten or not.
Throws:
DepotException - if an error occurs or replace is cancelled.

sync

public void sync()
          throws DepotException
Synchronize updating contents with the file and the device.

Throws:
DepotException - if an error occurs.
Note:
This method is useful when another process uses the connected database file.

version

public static java.lang.String version()
Get the version information.

Returns:
the string of the version information.

vsiz

public int vsiz(byte[] key)
         throws DepotException
Get the size of the value of a record.

Parameters:
key - a byte array of a key.
Returns:
the size of the value of the corresponding record. If the silent flag is true and no record corresponds, -1 is returned instead of exception.
Throws:
DepotException - if an error occurs or no record corresponds.
Note:
Because this method does not read the entity of a record, it is faster than `get'.

writable

public boolean writable()
                 throws DepotException
Check whether the database handle is a writer or not.

Returns:
true if the handle is a writer, false if not.
Throws:
DepotException - if an error occurs.


qdbm-1.8.78/java/japidoc/qdbm/package-frame.html0000644000175000017500000000362411426320065020376 0ustar mikiomikio qdbm (qdbm) qdbm
Interfaces 
ADBM
Classes 
Curia
Depot
Util
Villa
VillaCursor
Exceptions 
CuriaException
DBMException
DepotException
VillaException
qdbm-1.8.78/java/japidoc/qdbm/package-tree.html0000644000175000017500000001346111426320065020243 0ustar mikiomikio qdbm Class Hierarchy (qdbm)

Hierarchy For Package qdbm

Class Hierarchy

Interface Hierarchy



qdbm-1.8.78/java/japidoc/qdbm/DepotException.html0000644000175000017500000002446011426320065020646 0ustar mikiomikio DepotException (qdbm)

qdbm
Class DepotException

java.lang.Object
  extended by java.lang.Throwable
      extended by java.lang.Exception
          extended by qdbm.DBMException
              extended by qdbm.DepotException
All Implemented Interfaces:
java.io.Serializable

public class DepotException
extends DBMException

Exception container of Depot.

See Also:
Serialized Form

Field Summary
 int ecode
          error code
 
Constructor Summary
DepotException()
          Set the error code with `Depot.EMISC'.
DepotException(int ecode)
          Set the error code.
 
Method Summary
 
Methods inherited from class java.lang.Throwable
fillInStackTrace, getCause, getLocalizedMessage, getMessage, getStackTrace, initCause, printStackTrace, printStackTrace, printStackTrace, setStackTrace, toString
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
 

Field Detail

ecode

public final int ecode
error code

Constructor Detail

DepotException

public DepotException()
Set the error code with `Depot.EMISC'.


DepotException

public DepotException(int ecode)
Set the error code.

Parameters:
ecode - an error code.


qdbm-1.8.78/java/japidoc/qdbm/package-summary.html0000644000175000017500000001600011426320065020771 0ustar mikiomikio qdbm (qdbm)

Package qdbm

Interface Summary
ADBM Abstraction for database managers compatible with DBM.
 

Class Summary
Curia The Java API of Curia, the extended API of QDBM.
Depot The Java API of Depot, the basic API of QDBM.
Util Class of utility methods.
Villa The Java API of Villa, the advanced API of QDBM.
VillaCursor The Java API of cursor functions of Villa This class depends on the native library `jqdbm'.
 

Exception Summary
CuriaException Exception container of Curia.
DBMException Exception container of ADBM.
DepotException Exception container of Depot.
VillaException Exception container of Villa.
 



qdbm-1.8.78/java/japidoc/qdbm/Util.html0000644000175000017500000004010611426320065016624 0ustar mikiomikio Util (qdbm)

qdbm
Class Util

java.lang.Object
  extended by qdbm.Util

public class Util
extends java.lang.Object

Class of utility methods. This class depends on the native library `jqdbm'.


Method Summary
static int chdir(java.lang.String path)
          Change current working directory using the native function `chdir' defined in POSIX.
static java.lang.Object deserialize(byte[] serial)
          Redintegrate a serialized object.
static long deserializeLong(byte[] serial)
          Redintegrate a serialized long integer.
static java.lang.String getcwd()
          Get current working directory using the native function `getcwd' defined in POSIX.
static java.lang.String getenv(java.lang.String name)
          Get an environment variable using the native function `getenv' defined in POSIX and ANSI C.
static int getpid()
          Get process identification using the native function `getpid' defined in POSIX.
static java.lang.String numstr(int num, int cols, char padding)
          Get a formatted decimal string made from a number.
static byte[] readFile(java.lang.String path)
          Read whole data of a file.
static byte[] serialize(java.lang.Object obj)
          Serialize an object.
static byte[] serializeLong(long num)
          Serialize a long integer.
static int system(java.lang.String cmd)
          Execute a shell command using the native function `system' defined in POSIX and ANSI C.
static boolean writeFile(java.lang.String path, byte[] data)
          Write whole data to a file.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Method Detail

chdir

public static int chdir(java.lang.String path)
Change current working directory using the native function `chdir' defined in POSIX.

Parameters:
path - the path of a directory.
Returns:
0 on success, or -1 on failure.

deserialize

public static java.lang.Object deserialize(byte[] serial)
Redintegrate a serialized object.

Parameters:
serial - a byte array of the serialized object.
Returns:
an original object or null if an error occurs.

deserializeLong

public static long deserializeLong(byte[] serial)
                            throws java.lang.IllegalArgumentException
Redintegrate a serialized long integer.

Parameters:
serial - a byte array of a serialized long integer.
Returns:
the long value.
Throws:
java.lang.IllegalArgumentException - thrown if the size of the array is invalid.

getcwd

public static java.lang.String getcwd()
Get current working directory using the native function `getcwd' defined in POSIX.

Returns:
the path of the current working directory or null on failure.

getenv

public static java.lang.String getenv(java.lang.String name)
Get an environment variable using the native function `getenv' defined in POSIX and ANSI C.

Parameters:
name - the name of an environment variable.
Returns:
the value of the variable, or null if it does not exist.

getpid

public static int getpid()
Get process identification using the native function `getpid' defined in POSIX.

Returns:
the process ID of the current process.

numstr

public static java.lang.String numstr(int num,
                                      int cols,
                                      char padding)
Get a formatted decimal string made from a number.

Parameters:
num - a number.
cols - the number of columns. The result string may be longer than it.
padding - a padding character to fulfil columns with.

readFile

public static byte[] readFile(java.lang.String path)
Read whole data of a file.

Parameters:
path - the path of a file.
Returns:
while data of a file on success, or null on failure.

serialize

public static byte[] serialize(java.lang.Object obj)
Serialize an object.

Parameters:
obj - a serializable object.
Returns:
a byte array of the serialized object or null if an error occurs.

serializeLong

public static byte[] serializeLong(long num)
Serialize a long integer.

Parameters:
num - a long integer.
Returns:
a byte array of the serialized long integer.

system

public static int system(java.lang.String cmd)
Execute a shell command using the native function `system' defined in POSIX and ANSI C.

Parameters:
cmd - a command line.
Returns:
the return value of the function. It depends on the native system.

writeFile

public static boolean writeFile(java.lang.String path,
                                byte[] data)
Write whole data to a file.

Parameters:
path - the path of a file.
data - data to write.
Returns:
true if success, false on failure.


qdbm-1.8.78/java/japidoc/qdbm/VillaCursor.html0000644000175000017500000004532011426320065020157 0ustar mikiomikio VillaCursor (qdbm)

qdbm
Class VillaCursor

java.lang.Object
  extended by qdbm.VillaCursor

public class VillaCursor
extends java.lang.Object

The Java API of cursor functions of Villa This class depends on the native library `jqdbm'.


Method Summary
protected  void finalize()
          Release resources.
 boolean first()
          Move the multiple cursor to the first record.
 boolean jump(byte[] key)
          Move the multiple cursor to a position around a record for stepping forward.
 boolean jump(byte[] key, int jmode)
          Move the multiple cursor to a position around a record.
 boolean jumpobj(java.lang.Object key, int jmode)
          Move the multiple cursor to a position around a record composed of serializable objects.
 byte[] key()
          Get the key of the record where the multiple cursor is.
 java.lang.Object keyobj()
          Get the key of the record composed of serializable objects, where the multiple cursor is.
 boolean last()
          Move the multiple cursor to the last record.
 boolean next()
          Move the multiple cursor to the next record.
 boolean prev()
          Move the multiple cursor to the next record.
 byte[] val()
          Get the value of the record where the multiple cursor is.
 java.lang.Object valobj()
          Get the value of the record where the multiple cursor is.
 
Methods inherited from class java.lang.Object
clone, equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Method Detail

finalize

protected void finalize()
Release resources.

Overrides:
finalize in class java.lang.Object

first

public boolean first()
              throws VillaException
Move the multiple cursor to the first record.

Returns:
always true. However, if the silent flag is true and no record corresponds, false is returned instead of exception.
Throws:
VillaException - if an error occurs or there is no record in the database.

jump

public boolean jump(byte[] key)
             throws VillaException
Move the multiple cursor to a position around a record for stepping forward. The same as `jump(key, Villa.JFORFARD)'.

Throws:
VillaException
See Also:
jump(byte[], int)

jump

public boolean jump(byte[] key,
                    int jmode)
             throws VillaException
Move the multiple cursor to a position around a record.

Parameters:
key - a byte array of a key.
jmode - detail adjustment: `Villa.JFORWARD', which means that the cursor is set to the first record of the same key and that the cursor is set to the next substitute if completely matching record does not exist, `Villa.JBACKWARD', which means that the cursor is set to the last record of the same key and that the cursor is set to the previous substitute if completely matching record does not exist.
Returns:
always true. However, if the silent flag is true and no record corresponds, false is returned instead of exception.
Throws:
VillaException - if an error occurs or there is no record corresponding the condition.

jumpobj

public boolean jumpobj(java.lang.Object key,
                       int jmode)
                throws VillaException
Move the multiple cursor to a position around a record composed of serializable objects. The same as `jump(qdbm.Util.serialize(key), jmode)'.

Throws:
VillaException
See Also:
jump(byte[], int)
Note:
If serialization is failed, an instance of `VillaException' is thrown.

key

public byte[] key()
           throws VillaException
Get the key of the record where the multiple cursor is.

Returns:
a byte array of the key of the corresponding record. If the silent flag is true and no record corresponds, `null' is returned instead of exception.
Throws:
VillaException - if an error occurs or no record corresponds to the cursor.

keyobj

public java.lang.Object keyobj()
                        throws VillaException
Get the key of the record composed of serializable objects, where the multiple cursor is. The same as `qdbm.Util.deserialize(key())'.

Throws:
VillaException
See Also:
key()
Note:
If serialization is failed, an instance of `VillaException' is thrown.

last

public boolean last()
             throws VillaException
Move the multiple cursor to the last record.

Returns:
always true. However, if the silent flag is true and no record corresponds, false is returned instead of exception.
Throws:
VillaException - if an error occurs or there is no record in the database.

next

public boolean next()
             throws VillaException
Move the multiple cursor to the next record.

Returns:
always true. However, if the silent flag is true and no record corresponds, false is returned instead of exception.
Throws:
VillaException - if an error occurs or there is no next record.

prev

public boolean prev()
             throws VillaException
Move the multiple cursor to the next record.

Returns:
always true. However, if the silent flag is true and no record corresponds, false is returned instead of exception.
Throws:
VillaException - if an error occurs or there is no previous record.

val

public byte[] val()
           throws VillaException
Get the value of the record where the multiple cursor is.

Returns:
a byte array of the value of the corresponding record. If the silent flag is true and no record corresponds, `null' is returned instead of exception.
Throws:
VillaException - if an error occurs or no record corresponds to the cursor.

valobj

public java.lang.Object valobj()
                        throws VillaException
Get the value of the record where the multiple cursor is. The same as `qdbm.Util.deserialize(val())'.

Throws:
VillaException
See Also:
val()
Note:
If serialization is failed, an instance of `VillaException' is thrown.


qdbm-1.8.78/java/japidoc/qdbm/ADBM.html0000644000175000017500000002772111426320064016421 0ustar mikiomikio ADBM (qdbm)

qdbm
Interface ADBM

All Known Implementing Classes:
Curia, Depot, Villa

public interface ADBM

Abstraction for database managers compatible with DBM.


Method Summary
 void close()
          Close the database connection.
 void delete(byte[] key)
          Delete a record.
 boolean error()
          Check whether a fatal error occured or not.
 byte[] fetch(byte[] key)
          Fetch a record.
 byte[] firstkey()
          Get the first key.
 byte[] nextkey()
          Get the next key.
 void store(byte[] key, byte[] val, boolean replace)
          Store a record.
 

Method Detail

close

void close()
           throws DBMException
Close the database connection.

Throws:
DBMException - if an error occurs.

delete

void delete(byte[] key)
            throws DBMException
Delete a record.

Parameters:
key - a byte array of a key.
Throws:
DBMException - if an error occurs or no record corresponds.

error

boolean error()
              throws DBMException
Check whether a fatal error occured or not.

Returns:
true if the database has a fatal error, false if not.
Throws:
DBMException - if an error occurs.

fetch

byte[] fetch(byte[] key)
             throws DBMException
Fetch a record.

Parameters:
key - a byte array of a key.
Returns:
a byte array of the value of the corresponding record.
Throws:
DBMException - if an error occurs or no record corresponds.

firstkey

byte[] firstkey()
                throws DBMException
Get the first key.

Returns:
a byte array of the key of the first record.
Throws:
DBMException - if an error occurs or no record corresponds.

nextkey

byte[] nextkey()
               throws DBMException
Get the next key.

Returns:
a byte array of the key of the next record.
Throws:
DBMException - if an error occurs or no record corresponds.

store

void store(byte[] key,
           byte[] val,
           boolean replace)
           throws DBMException
Store a record.

Parameters:
key - a byte array of a key.
val - a byte array of a value.
replace - whether the existing value is to be overwritten or not.
Throws:
DBMException - if an error occurs or replace is cancelled.


qdbm-1.8.78/java/japidoc/qdbm/VillaException.html0000644000175000017500000002430211426320065020635 0ustar mikiomikio VillaException (qdbm)

qdbm
Class VillaException

java.lang.Object
  extended by java.lang.Throwable
      extended by java.lang.Exception
          extended by qdbm.DBMException
              extended by qdbm.VillaException
All Implemented Interfaces:
java.io.Serializable

public class VillaException
extends DBMException

Exception container of Villa.

See Also:
Serialized Form

Field Summary
 int ecode
          error code
 
Constructor Summary
VillaException()
          Set the error code with `Villa.EMISC'.
VillaException(int ecode)
          Set the error code.
 
Method Summary
 
Methods inherited from class java.lang.Throwable
fillInStackTrace, getCause, getLocalizedMessage, getMessage, getStackTrace, initCause, printStackTrace, printStackTrace, printStackTrace, setStackTrace, toString
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
 

Field Detail

ecode

public final int ecode
error code

Constructor Detail

VillaException

public VillaException()
Set the error code with `Villa.EMISC'.


VillaException

public VillaException(int ecode)
Set the error code.

Parameters:
ecode - an error code.


qdbm-1.8.78/java/japidoc/package-list0000644000175000017500000000000511426320065016357 0ustar mikiomikioqdbm qdbm-1.8.78/java/japidoc/allclasses-frame.html0000644000175000017500000000276311426320065020211 0ustar mikiomikio All Classes (qdbm) All Classes
ADBM
Curia
CuriaException
DBMException
Depot
DepotException
Util
Villa
VillaCursor
VillaException
qdbm-1.8.78/java/japidoc/allclasses-noframe.html0000644000175000017500000000245311426320065020542 0ustar mikiomikio All Classes (qdbm) All Classes
ADBM
Curia
CuriaException
DBMException
Depot
DepotException
Util
Villa
VillaCursor
VillaException
qdbm-1.8.78/java/japidoc/constant-values.html0000644000175000017500000011172011426320065020113 0ustar mikiomikio Constant Field Values (qdbm)

Constant Field Values


Contents
qdbm.*

qdbm.Curia
public static final int DCAT 2
public static final int DKEEP 1
public static final int DOVER 0
public static final int EALLOC 6
public static final int EBROKEN 3
public static final int ECLOSE 9
public static final int EFATAL 1
public static final int EKEEP 4
public static final int ELOCK 16
public static final int EMAP 7
public static final int EMISC 20
public static final int EMKDIR 18
public static final int EMODE 2
public static final int ENOERR 0
public static final int ENOITEM 5
public static final int EOPEN 8
public static final int EREAD 14
public static final int ERMDIR 19
public static final int ESEEK 13
public static final int ESTAT 12
public static final int ESYNC 11
public static final int ETRUNC 10
public static final int EUNLINK 17
public static final int EWRITE 15
public static final int OCREAT 4
public static final int OLCKNB 32
public static final int ONOLCK 16
public static final int OREADER 1
public static final int OSPARSE 64
public static final int OTRUNC 8
public static final int OWRITER 2

qdbm.Depot
public static final int DCAT 2
public static final int DKEEP 1
public static final int DOVER 0
public static final int EALLOC 6
public static final int EBROKEN 3
public static final int ECLOSE 9
public static final int EFATAL 1
public static final int EKEEP 4
public static final int ELOCK 16
public static final int EMAP 7
public static final int EMISC 20
public static final int EMKDIR 18
public static final int EMODE 2
public static final int ENOERR 0
public static final int ENOITEM 5
public static final int EOPEN 8
public static final int EREAD 14
public static final int ERMDIR 19
public static final int ESEEK 13
public static final int ESTAT 12
public static final int ESYNC 11
public static final int ETRUNC 10
public static final int EUNLINK 17
public static final int EWRITE 15
public static final int OCREAT 4
public static final int OLCKNB 32
public static final int ONOLCK 16
public static final int OREADER 1
public static final int OSPARSE 64
public static final int OTRUNC 8
public static final int OWRITER 2

qdbm.Villa
public static final int CMPDEC 2
public static final int CMPLEX 0
public static final int CMPNUM 1
public static final int CMPOBJ 3
public static final int CPAFTER 2
public static final int CPBEFORE 1
public static final int CPCURRENT 0
public static final int DCAT 2
public static final int DDUP 3
public static final int DDUPR 4
public static final int DKEEP 1
public static final int DOVER 0
public static final int EALLOC 6
public static final int EBROKEN 3
public static final int ECLOSE 9
public static final int EFATAL 1
public static final int EKEEP 4
public static final int ELOCK 16
public static final int EMAP 7
public static final int EMISC 20
public static final int EMKDIR 18
public static final int EMODE 2
public static final int ENOERR 0
public static final int ENOITEM 5
public static final int EOPEN 8
public static final int EREAD 14
public static final int ERMDIR 19
public static final int ESEEK 13
public static final int ESTAT 12
public static final int ESYNC 11
public static final int ETRUNC 10
public static final int EUNLINK 17
public static final int EWRITE 15
public static final int JBACKWARD 1
public static final int JFORWARD 0
public static final int OCREAT 4
public static final int OLCKNB 32
public static final int ONOLCK 16
public static final int OREADER 1
public static final int OTRUNC 8
public static final int OWRITER 2
public static final int OXCOMP 256
public static final int OYCOMP 128
public static final int OZCOMP 64



qdbm-1.8.78/java/japidoc/index-all.html0000644000175000017500000017465211426320065016657 0ustar mikiomikio Index (qdbm)
A B C D E F G I J K L M N O P Q R S T U V W

A

ADBM - Interface in qdbm
Abstraction for database managers compatible with DBM.

B

bnum() - Method in class qdbm.Curia
Get the total number of the elements of each bucket array.
bnum() - Method in class qdbm.Depot
Get the number of the elements of the bucket array.
busenum() - Method in class qdbm.Curia
Get the total number of the used elements of each bucket array.
busenum() - Method in class qdbm.Depot
Get the number of the used elements of the bucket array.

C

chdir(String) - Static method in class qdbm.Util
Change current working directory using the native function `chdir' defined in POSIX.
close() - Method in interface qdbm.ADBM
Close the database connection.
close() - Method in class qdbm.Curia
Close the database handle.
close() - Method in class qdbm.Depot
Close the database handle.
close() - Method in class qdbm.Villa
Close the database handle.
CMPDEC - Static variable in class qdbm.Villa
comparing mode: compare as decimal strings
CMPLEX - Static variable in class qdbm.Villa
comparing mode: compare by lexical order
CMPNUM - Static variable in class qdbm.Villa
comparing mode: compare as long integers
CMPOBJ - Static variable in class qdbm.Villa
comparing mode: compare as comparable objects
CPAFTER - Static variable in class qdbm.Villa
insertion mode: insert after the current record
CPBEFORE - Static variable in class qdbm.Villa
insertion mode: insert before the current record
CPCURRENT - Static variable in class qdbm.Villa
insertion mode: overwrite the current record
curfirst() - Method in class qdbm.Villa
Move the cursor to the first record.
Curia - Class in qdbm
The Java API of Curia, the extended API of QDBM.
Curia(String, int, int, int) - Constructor for class qdbm.Curia
Get the database handle.
Curia(String) - Constructor for class qdbm.Curia
Get the database handle as a reader.
CuriaException - Exception in qdbm
Exception container of Curia.
CuriaException() - Constructor for exception qdbm.CuriaException
Set the error code with `Curia.EMISC'.
CuriaException(int) - Constructor for exception qdbm.CuriaException
Set the error code.
curjump(byte[], int) - Method in class qdbm.Villa
Move the cursor to a position around a record.
curjump(byte[]) - Method in class qdbm.Villa
Move the cursor to a position around a record for stepping forward.
curjumpobj(Object, int) - Method in class qdbm.Villa
Move the cursor to a position around a record composed of serializable objects.
curkey() - Method in class qdbm.Villa
Get the key of the record where the cursor is.
curkeyobj() - Method in class qdbm.Villa
Get the key of the record composed of serializable objects, where the cursor is.
curlast() - Method in class qdbm.Villa
Move the cursor to the last record.
curnext() - Method in class qdbm.Villa
Move the cursor to the next record.
curout() - Method in class qdbm.Villa
Delete the record where the cursor is.
curprev() - Method in class qdbm.Villa
Move the cursor to the next record.
curput(byte[], int) - Method in class qdbm.Villa
Insert a record around the cursor.
curput(byte[]) - Method in class qdbm.Villa
Insert a record as the successor of the cursor.
curputobj(Object, int) - Method in class qdbm.Villa
Insert a record around the cursor.
curval() - Method in class qdbm.Villa
Get the value of the record where the cursor is.
curvalobj() - Method in class qdbm.Villa
Get the value of the record where the cursor is.

D

DBMException - Exception in qdbm
Exception container of ADBM.
DBMException() - Constructor for exception qdbm.DBMException
Nothing specified.
DBMException(String) - Constructor for exception qdbm.DBMException
Nothing specified.
DCAT - Static variable in class qdbm.Curia
write mode: concatenate values
DCAT - Static variable in class qdbm.Depot
write mode: concatenate values
DCAT - Static variable in class qdbm.Villa
write mode: concatenate values
DDUP - Static variable in class qdbm.Villa
write mode: allow duplication of records
DDUPR - Static variable in class qdbm.Villa
write mode: allow duplication with reverse order
delete(byte[]) - Method in interface qdbm.ADBM
Delete a record.
delete(byte[]) - Method in class qdbm.Curia
Delete a record.
delete(byte[]) - Method in class qdbm.Depot
Delete a record.
delete(byte[]) - Method in class qdbm.Villa
Delete a record.
Depot - Class in qdbm
The Java API of Depot, the basic API of QDBM.
Depot(String, int, int) - Constructor for class qdbm.Depot
Get the database handle.
Depot(String) - Constructor for class qdbm.Depot
Get the database handle as a reader.
DepotException - Exception in qdbm
Exception container of Depot.
DepotException() - Constructor for exception qdbm.DepotException
Set the error code with `Depot.EMISC'.
DepotException(int) - Constructor for exception qdbm.DepotException
Set the error code.
deserialize(byte[]) - Static method in class qdbm.Util
Redintegrate a serialized object.
deserializeLong(byte[]) - Static method in class qdbm.Util
Redintegrate a serialized long integer.
DKEEP - Static variable in class qdbm.Curia
write mode: keep the existing value
DKEEP - Static variable in class qdbm.Depot
write mode: keep the existing value
DKEEP - Static variable in class qdbm.Villa
write mode: keep the existing value
DOVER - Static variable in class qdbm.Curia
write mode: overwrite the existing value
DOVER - Static variable in class qdbm.Depot
write mode: overwrite the existing value
DOVER - Static variable in class qdbm.Villa
write mode: overwrite the existing value

E

EALLOC - Static variable in class qdbm.Curia
error code: memory allocation error
EALLOC - Static variable in class qdbm.Depot
error code: memory allocation error
EALLOC - Static variable in class qdbm.Villa
error code: memory allocation error
EBROKEN - Static variable in class qdbm.Curia
error code: broken database file
EBROKEN - Static variable in class qdbm.Depot
error code: broken database file
EBROKEN - Static variable in class qdbm.Villa
error code: broken database file
ECLOSE - Static variable in class qdbm.Curia
error code: close error
ECLOSE - Static variable in class qdbm.Depot
error code: close error
ECLOSE - Static variable in class qdbm.Villa
error code: close error
ecode - Variable in exception qdbm.CuriaException
error code
ecode - Variable in exception qdbm.DepotException
error code
ecode - Variable in exception qdbm.VillaException
error code
EFATAL - Static variable in class qdbm.Curia
error code: with fatal error
EFATAL - Static variable in class qdbm.Depot
error code: with fatal error
EFATAL - Static variable in class qdbm.Villa
error code: with fatal error
EKEEP - Static variable in class qdbm.Curia
error code: existing record
EKEEP - Static variable in class qdbm.Depot
error code: existing record
EKEEP - Static variable in class qdbm.Villa
error code: existing record
ELOCK - Static variable in class qdbm.Curia
error code: lock error
ELOCK - Static variable in class qdbm.Depot
error code: lock error
ELOCK - Static variable in class qdbm.Villa
error code: lock error
EMAP - Static variable in class qdbm.Curia
error code: memory mapping error
EMAP - Static variable in class qdbm.Depot
error code: memory mapping error
EMAP - Static variable in class qdbm.Villa
error code: memory mapping error
EMISC - Static variable in class qdbm.Curia
error code: miscellaneous error
EMISC - Static variable in class qdbm.Depot
error code: miscellaneous error
EMISC - Static variable in class qdbm.Villa
error code: miscellaneous error
EMKDIR - Static variable in class qdbm.Curia
error code: mkdir error
EMKDIR - Static variable in class qdbm.Depot
error code: mkdir error
EMKDIR - Static variable in class qdbm.Villa
error code: mkdir error
EMODE - Static variable in class qdbm.Curia
error code: invalid mode
EMODE - Static variable in class qdbm.Depot
error code: invalid mode
EMODE - Static variable in class qdbm.Villa
error code: invalid mode
ENOERR - Static variable in class qdbm.Curia
error code: no error
ENOERR - Static variable in class qdbm.Depot
error code: no error
ENOERR - Static variable in class qdbm.Villa
error code: no error
ENOITEM - Static variable in class qdbm.Curia
error code: no item found
ENOITEM - Static variable in class qdbm.Depot
error code: no item found
ENOITEM - Static variable in class qdbm.Villa
error code: no item found
EOPEN - Static variable in class qdbm.Curia
error code: open error
EOPEN - Static variable in class qdbm.Depot
error code: open error
EOPEN - Static variable in class qdbm.Villa
error code: open error
EREAD - Static variable in class qdbm.Curia
error code: read error
EREAD - Static variable in class qdbm.Depot
error code: read error
EREAD - Static variable in class qdbm.Villa
error code: read error
ERMDIR - Static variable in class qdbm.Curia
error code: rmdir error
ERMDIR - Static variable in class qdbm.Depot
error code: rmdir error
ERMDIR - Static variable in class qdbm.Villa
error code: rmdir error
errmsg(int) - Static method in class qdbm.Curia
Get an error message.
errmsg(int) - Static method in class qdbm.Depot
Get an error message.
errmsg(int) - Static method in class qdbm.Villa
Get an error message.
error() - Method in interface qdbm.ADBM
Check whether a fatal error occured or not.
error() - Method in class qdbm.Curia
Check whether a fatal error occured or not.
error() - Method in class qdbm.Depot
Check whether a fatal error occured or not.
error() - Method in class qdbm.Villa
Check whether a fatal error occured or not.
ESEEK - Static variable in class qdbm.Curia
error code: seek error
ESEEK - Static variable in class qdbm.Depot
error code: seek error
ESEEK - Static variable in class qdbm.Villa
error code: seek error
ESTAT - Static variable in class qdbm.Curia
error code: stat error
ESTAT - Static variable in class qdbm.Depot
error code: stat error
ESTAT - Static variable in class qdbm.Villa
error code: stat error
ESYNC - Static variable in class qdbm.Curia
error code: sync error
ESYNC - Static variable in class qdbm.Depot
error code: sync error
ESYNC - Static variable in class qdbm.Villa
error code: sync error
ETRUNC - Static variable in class qdbm.Curia
error code: trunc error
ETRUNC - Static variable in class qdbm.Depot
error code: trunc error
ETRUNC - Static variable in class qdbm.Villa
error code: trunc error
EUNLINK - Static variable in class qdbm.Curia
error code: unlink error
EUNLINK - Static variable in class qdbm.Depot
error code: unlink error
EUNLINK - Static variable in class qdbm.Villa
error code: unlink error
EWRITE - Static variable in class qdbm.Curia
error code: write error
EWRITE - Static variable in class qdbm.Depot
error code: write error
EWRITE - Static variable in class qdbm.Villa
error code: write error

F

fatalerror() - Method in class qdbm.Curia
Check whether the database has a fatal error or not.
fatalerror() - Method in class qdbm.Depot
Check whether the database has a fatal error or not.
fatalerror() - Method in class qdbm.Villa
Check whether the database has a fatal error or not.
fetch(byte[]) - Method in interface qdbm.ADBM
Fetch a record.
fetch(byte[]) - Method in class qdbm.Curia
Fetch a record.
fetch(byte[]) - Method in class qdbm.Depot
Fetch a record.
fetch(byte[]) - Method in class qdbm.Villa
Fetch a record.
finalize() - Method in class qdbm.Curia
Release the resources.
finalize() - Method in class qdbm.Depot
Release the resources.
finalize() - Method in class qdbm.Villa
Release the resources.
finalize() - Method in class qdbm.VillaCursor
Release resources.
first() - Method in class qdbm.VillaCursor
Move the multiple cursor to the first record.
firstkey() - Method in interface qdbm.ADBM
Get the first key.
firstkey() - Method in class qdbm.Curia
Get the first key.
firstkey() - Method in class qdbm.Depot
Get the first key.
firstkey() - Method in class qdbm.Villa
Get the first key.
fsiz() - Method in class qdbm.Curia
Get the total size of the database files.
fsiz() - Method in class qdbm.Depot
Get the size of the database file.
fsiz() - Method in class qdbm.Villa
Get the size of the database file.

G

get(byte[], int, int) - Method in class qdbm.Curia
Retrieve a record.
get(byte[]) - Method in class qdbm.Curia
Retrieve whole value of a record.
get(byte[], int, int) - Method in class qdbm.Depot
Retrieve a record.
get(byte[]) - Method in class qdbm.Depot
Retrieve whole value of a record.
get(byte[]) - Method in class qdbm.Villa
Retrieve a record.
getcwd() - Static method in class qdbm.Util
Get current working directory using the native function `getcwd' defined in POSIX.
getenv(String) - Static method in class qdbm.Util
Get an environment variable using the native function `getenv' defined in POSIX and ANSI C.
getindex() - Method in class qdbm.Villa
Get the index of the native table for database handles.
getlob(byte[], int, int) - Method in class qdbm.Curia
Retrieve a large object.
getlob(byte[]) - Method in class qdbm.Curia
Retrieve whole value of a large object.
getobj(Object) - Method in class qdbm.Villa
Retrieve a record composed of serializable objects.
getpid() - Static method in class qdbm.Util
Get process identification using the native function `getpid' defined in POSIX.

I

inode() - Method in class qdbm.Curia
Get the inode number of the database.
inode() - Method in class qdbm.Depot
Get the inode number of the database.
inode() - Method in class qdbm.Villa
Get the inode number of the database.
iterinit() - Method in class qdbm.Curia
Initialize the iterator of the database handle.
iterinit() - Method in class qdbm.Depot
Initialize the iterator of the database handle.
iternext() - Method in class qdbm.Curia
Get the next key of the iterator.
iternext() - Method in class qdbm.Depot
Get the next key of the iterator.

J

JBACKWARD - Static variable in class qdbm.Villa
jump mode: jump mode: step backward
JFORWARD - Static variable in class qdbm.Villa
jump mode: jump mode: step forward
jump(byte[], int) - Method in class qdbm.VillaCursor
Move the multiple cursor to a position around a record.
jump(byte[]) - Method in class qdbm.VillaCursor
Move the multiple cursor to a position around a record for stepping forward.
jumpobj(Object, int) - Method in class qdbm.VillaCursor
Move the multiple cursor to a position around a record composed of serializable objects.

K

key() - Method in class qdbm.VillaCursor
Get the key of the record where the multiple cursor is.
keyobj() - Method in class qdbm.VillaCursor
Get the key of the record composed of serializable objects, where the multiple cursor is.

L

last() - Method in class qdbm.VillaCursor
Move the multiple cursor to the last record.
lnum() - Method in class qdbm.Villa
Get the number of the leaf nodes of B+ tree.

M

mtime() - Method in class qdbm.Curia
Get the last modified time of the database.
mtime() - Method in class qdbm.Depot
Get the last modified time of the database.
mtime() - Method in class qdbm.Villa
Get the last modified time of the database.
mulcuropen() - Method in class qdbm.Villa
Get a multiple cursor.

N

name() - Method in class qdbm.Curia
Get the name of the database.
name() - Method in class qdbm.Depot
Get the name of the database.
name() - Method in class qdbm.Villa
Get the name of the database.
next() - Method in class qdbm.VillaCursor
Move the multiple cursor to the next record.
nextkey() - Method in interface qdbm.ADBM
Get the next key.
nextkey() - Method in class qdbm.Curia
Get the next key.
nextkey() - Method in class qdbm.Depot
Get the next key.
nextkey() - Method in class qdbm.Villa
Get the next key.
nnum() - Method in class qdbm.Villa
Get the number of the non-leaf nodes of B+ tree.
numstr(int, int, char) - Static method in class qdbm.Util
Get a formatted decimal string made from a number.

O

OCREAT - Static variable in class qdbm.Curia
open mode: writer creating
OCREAT - Static variable in class qdbm.Depot
open mode: writer creating
OCREAT - Static variable in class qdbm.Villa
open mode: writer creating
OLCKNB - Static variable in class qdbm.Curia
open mode: lock without blocking
OLCKNB - Static variable in class qdbm.Depot
open mode: lock without blocking
OLCKNB - Static variable in class qdbm.Villa
open mode: lock without blocking
ONOLCK - Static variable in class qdbm.Curia
open mode: open without locking
ONOLCK - Static variable in class qdbm.Depot
open mode: open without locking
ONOLCK - Static variable in class qdbm.Villa
open mode: open without locking
optimize(int) - Method in class qdbm.Curia
Optimize the database.
optimize(int) - Method in class qdbm.Depot
Optimize the database.
optimize() - Method in class qdbm.Villa
Optimize the database.
OREADER - Static variable in class qdbm.Curia
open mode: open as a reader
OREADER - Static variable in class qdbm.Depot
open mode: open as a reader
OREADER - Static variable in class qdbm.Villa
open mode: open as a reader
OSPARSE - Static variable in class qdbm.Curia
open mode: create as sparse files
OSPARSE - Static variable in class qdbm.Depot
open mode: create as a sparse file
OTRUNC - Static variable in class qdbm.Curia
open mode: writer truncating
OTRUNC - Static variable in class qdbm.Depot
open mode: writer truncating
OTRUNC - Static variable in class qdbm.Villa
open mode: writer truncating
out(byte[]) - Method in class qdbm.Curia
Delete a record.
out(byte[]) - Method in class qdbm.Depot
Delete a record.
out(byte[]) - Method in class qdbm.Villa
Delete a record.
outlob(byte[]) - Method in class qdbm.Curia
Delete a large object.
outobj(Object) - Method in class qdbm.Villa
Delete a record composed of serializable objects.
OWRITER - Static variable in class qdbm.Curia
open mode: open as a writer
OWRITER - Static variable in class qdbm.Depot
open mode: open as a writer
OWRITER - Static variable in class qdbm.Villa
open mode: open as a writer
OXCOMP - Static variable in class qdbm.Villa
open mode: compress leaves with BZIP2
OYCOMP - Static variable in class qdbm.Villa
open mode: compress leaves with LZO
OZCOMP - Static variable in class qdbm.Villa
open mode: compress leaves with ZLIB

P

prev() - Method in class qdbm.VillaCursor
Move the multiple cursor to the next record.
put(byte[], byte[], int) - Method in class qdbm.Curia
Store a record.
put(byte[], byte[]) - Method in class qdbm.Curia
Store a record with overwrite.
put(byte[], byte[], int) - Method in class qdbm.Depot
Store a record.
put(byte[], byte[]) - Method in class qdbm.Depot
Store a record with overwrite.
put(byte[], byte[], int) - Method in class qdbm.Villa
Store a record.
put(byte[], byte[]) - Method in class qdbm.Villa
Store a record with overwrite.
putlob(byte[], byte[], int) - Method in class qdbm.Curia
Store a large object.
putlob(byte[], byte[]) - Method in class qdbm.Curia
Store a large object with overwrite.
putobj(Object, Object, int) - Method in class qdbm.Villa
Store a record composed of serializable objects.

Q

qdbm - package qdbm
 

R

readFile(String) - Static method in class qdbm.Util
Read whole data of a file.
remove(String) - Static method in class qdbm.Curia
Remove a database directory.
remove(String) - Static method in class qdbm.Depot
Remove a database file.
remove(String) - Static method in class qdbm.Villa
Remove a database file.
rnum() - Method in class qdbm.Curia
Get the number of the records stored in the database.
rnum() - Method in class qdbm.Depot
Get the number of the records stored in the database.
rnum() - Method in class qdbm.Villa
Get the number of the records stored in a database.
rnumlob() - Method in class qdbm.Curia
Get the number of the large objects stored in the database.

S

serialize(Object) - Static method in class qdbm.Util
Serialize an object.
serializeLong(long) - Static method in class qdbm.Util
Serialize a long integer.
setalign(int) - Method in class qdbm.Curia
Set alignment of the database handle.
setalign(int) - Method in class qdbm.Depot
Set alignment of the database handle.
setfbpsiz(int) - Method in class qdbm.Curia
Set the size of the free block pool.
setfbpsiz(int) - Method in class qdbm.Depot
Set the size of the free block pool.
settuning(int, int, int, int) - Method in class qdbm.Villa
Set the tuning parameters for performance.
silent - Variable in class qdbm.Curia
Whether to repress frequent exceptions.
silent - Variable in class qdbm.Depot
Whether to repress frequent exceptions.
silent - Variable in class qdbm.Villa
Whether to repress frequent exceptions.
snaffle(String, byte[]) - Static method in class qdbm.Curia
Retrieve a record directly from a database directory.
snaffle(String, byte[]) - Static method in class qdbm.Depot
Retrieve a record directly from a database file.
store(byte[], byte[], boolean) - Method in interface qdbm.ADBM
Store a record.
store(byte[], byte[], boolean) - Method in class qdbm.Curia
Store a record.
store(byte[], byte[], boolean) - Method in class qdbm.Depot
Store a record.
store(byte[], byte[], boolean) - Method in class qdbm.Villa
Store a record.
sync() - Method in class qdbm.Curia
Synchronize updating contents with the files and the devices.
sync() - Method in class qdbm.Depot
Synchronize updating contents with the file and the device.
sync() - Method in class qdbm.Villa
Synchronize updating contents with the file and the device.
system(String) - Static method in class qdbm.Util
Execute a shell command using the native function `system' defined in POSIX and ANSI C.

T

tranabort() - Method in class qdbm.Villa
Abort the transaction.
tranbegin() - Method in class qdbm.Villa
Begin the transaction.
trancommit() - Method in class qdbm.Villa
Commit the transaction.

U

Util - Class in qdbm
Class of utility methods.

V

val() - Method in class qdbm.VillaCursor
Get the value of the record where the multiple cursor is.
valobj() - Method in class qdbm.VillaCursor
Get the value of the record where the multiple cursor is.
version() - Static method in class qdbm.Curia
Get the version information.
version() - Static method in class qdbm.Depot
Get the version information.
version() - Static method in class qdbm.Villa
Get the version information.
Villa - Class in qdbm
The Java API of Villa, the advanced API of QDBM.
Villa(String, int, int) - Constructor for class qdbm.Villa
Get the database handle.
Villa(String) - Constructor for class qdbm.Villa
Get the database handle as a reader.
VillaCursor - Class in qdbm
The Java API of cursor functions of Villa This class depends on the native library `jqdbm'.
VillaException - Exception in qdbm
Exception container of Villa.
VillaException() - Constructor for exception qdbm.VillaException
Set the error code with `Villa.EMISC'.
VillaException(int) - Constructor for exception qdbm.VillaException
Set the error code.
vnum(byte[]) - Method in class qdbm.Villa
Get the number of records corresponding a key.
vnumobj(Object) - Method in class qdbm.Villa
Get the number of records corresponding a key, composed of serializable objects.
vsiz(byte[]) - Method in class qdbm.Curia
Get the size of the value of a record.
vsiz(byte[]) - Method in class qdbm.Depot
Get the size of the value of a record.
vsiz(byte[]) - Method in class qdbm.Villa
Get the size of the value of a record.
vsizlob(byte[]) - Method in class qdbm.Curia
Get the size of the value of a large object.
vsizobj(Object) - Method in class qdbm.Villa
Get the size of the value of a record, composed of serializable objects.

W

writable() - Method in class qdbm.Curia
Check whether the database handle is a writer or not.
writable() - Method in class qdbm.Depot
Check whether the database handle is a writer or not.
writable() - Method in class qdbm.Villa
Check whether the database handle is a writer or not.
writeFile(String, byte[]) - Static method in class qdbm.Util
Write whole data to a file.

A B C D E F G I J K L M N O P Q R S T U V W

qdbm-1.8.78/java/configure0000755000175000017500000035231211426320062014376 0ustar mikiomikio#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.65 for qdbm-java 1.0.0. # # # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, # 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, # Inc. # # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi " as_required="as_fn_return () { (exit \$1); } as_fn_success () { as_fn_return 0; } as_fn_failure () { as_fn_return 1; } as_fn_ret_success () { return 0; } as_fn_ret_failure () { return 1; } exitcode=0 as_fn_success || { exitcode=1; echo as_fn_success failed.; } as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : else exitcode=1; echo positional parameters were not saved. fi test x\$exitcode = x0 || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1" if (eval "$as_required") 2>/dev/null; then : as_have_required=yes else as_have_required=no fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. as_shell=$as_dir/$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : CONFIG_SHELL=$as_shell as_have_required=yes if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : break 2 fi fi done;; esac as_found=false done $as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : CONFIG_SHELL=$SHELL as_have_required=yes fi; } IFS=$as_save_IFS if test "x$CONFIG_SHELL" != x; then : # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV export CONFIG_SHELL exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"} fi if test x$as_have_required = xno; then : $as_echo "$0: This script requires a shell more modern than all" $as_echo "$0: the shells that I found on your system." if test x${ZSH_VERSION+set} = xset ; then $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" $as_echo "$0: be upgraded to zsh 4.3.4 or later." else $as_echo "$0: Please tell bug-autoconf@gnu.org about your system, $0: including any error possibly output before this $0: message. Then install a modern shell, or manually run $0: the script under such a shell if you do have one." fi exit 1 fi fi fi SHELL=${CONFIG_SHELL-/bin/sh} export SHELL # Unset more variables known to interfere with behavior of common tools. CLICOLOR_FORCE= GREP_OPTIONS= unset CLICOLOR_FORCE GREP_OPTIONS ## --------------------- ## ## M4sh Shell Functions. ## ## --------------------- ## # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error "cannot create directory $as_dir" } # as_fn_mkdir_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith # as_fn_error ERROR [LINENO LOG_FD] # --------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with status $?, using 1 if that was 0. as_fn_error () { as_status=$?; test $as_status -eq 0 && as_status=1 if test "$3"; then as_lineno=${as_lineno-"$2"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $1" >&$3 fi $as_echo "$as_me: error: $1" >&2 as_fn_exit $as_status } # as_fn_error if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits as_lineno_1=$LINENO as_lineno_1a=$LINENO as_lineno_2=$LINENO as_lineno_2a=$LINENO eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -p'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -p' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -p' fi else as_ln_s='cp -p' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi if test -x / >/dev/null 2>&1; then as_test_x='test -x' else if ls -dL / >/dev/null 2>&1; then as_ls_L_option=L else as_ls_L_option= fi as_test_x=' eval sh -c '\'' if test -d "$1"; then test -d "$1/."; else case $1 in #( -*)set "./$1";; esac; case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( ???[sx]*):;;*)false;;esac;fi '\'' sh ' fi as_executable_p=$as_test_x # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME='qdbm-java' PACKAGE_TARNAME='qdbm-java' PACKAGE_VERSION='1.0.0' PACKAGE_STRING='qdbm-java 1.0.0' PACKAGE_BUGREPORT='' PACKAGE_URL='' ac_subst_vars='LTLIBOBJS LIBOBJS LD MYOPTS MYDEFS JAVARUN JAVADOC JAVAH JAR JAVAC JVMPLATFORM MYJAVAHOME TARGETS LIBREV LIBVER OBJEXT EXEEXT ac_ct_CC CPPFLAGS LDFLAGS CFLAGS CC target_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_URL PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL' ac_subst_files='' ac_user_opts=' enable_option_checking enable_debug enable_devel with_gcj ' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS' # Initialize some variables set by options. ac_init_help= ac_init_version=false ac_unrecognized_opts= ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) as_fn_error "unrecognized option: \`$ac_option' Try \`$0 --help' for more information." ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) as_fn_error "invalid variable name: \`$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` as_fn_error "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) as_fn_error "unrecognized options: $ac_unrecognized_opts" ;; *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi # Check all directory arguments for consistency. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir do eval ac_val=\$$ac_var # Remove trailing slashes. case $ac_val in */ ) ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` eval $ac_var=\$ac_val;; esac # Be sure to have absolute directory names. case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac as_fn_error "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe $as_echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. If a cross compiler is detected then cross compile mode will be used." >&2 elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || as_fn_error "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || as_fn_error "pwd does not report name of working directory" # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." as_fn_error "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures qdbm-java 1.0.0 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/qdbm-java] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of qdbm-java 1.0.0:";; esac cat <<\_ACEOF Optional Features: --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --enable-debug build for debugging --enable-devel build for development Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-gcj build with gcj, gcc for Java Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to the package provider. _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for guested configure. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF qdbm-java configure 1.0.0 generated by GNU Autoconf 2.65 Copyright (C) 2009 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi ## ------------------------ ## ## Autoconf initialization. ## ## ------------------------ ## # ac_fn_c_try_compile LINENO # -------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} as_fn_set_status $ac_retval } # ac_fn_c_try_compile # ac_fn_c_try_link LINENO # ----------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} as_fn_set_status $ac_retval } # ac_fn_c_try_link cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by qdbm-java $as_me 1.0.0, which was generated by GNU Autoconf 2.65. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. $as_echo "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) as_fn_append ac_configure_args1 " '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done { ac_configure_args0=; unset ac_configure_args0;} { ac_configure_args1=; unset ac_configure_args1;} # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo cat <<\_ASBOX ## ---------------- ## ## Cache variables. ## ## ---------------- ## _ASBOX echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo cat <<\_ASBOX ## ----------------- ## ## Output variables. ## ## ----------------- ## _ASBOX echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then cat <<\_ASBOX ## ------------------- ## ## File substitutions. ## ## ------------------- ## _ASBOX echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then cat <<\_ASBOX ## ----------- ## ## confdefs.h. ## ## ----------- ## _ASBOX echo cat confdefs.h echo fi test "$ac_signal" != 0 && $as_echo "$as_me: caught signal $ac_signal" $as_echo "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h $as_echo "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_URL "$PACKAGE_URL" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. ac_site_file1=NONE ac_site_file2=NONE if test -n "$CONFIG_SITE"; then ac_site_file1=$CONFIG_SITE elif test "x$prefix" != xNONE; then ac_site_file1=$prefix/share/config.site ac_site_file2=$prefix/etc/config.site else ac_site_file1=$ac_default_prefix/share/config.site ac_site_file2=$ac_default_prefix/etc/config.site fi for ac_site_file in "$ac_site_file1" "$ac_site_file2" do test "x$ac_site_file" = xNONE && continue if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 $as_echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 $as_echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 $as_echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then # differences in whitespace do not lead to failure. ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 $as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 $as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 $as_echo "$as_me: former value: \`$ac_old_val'" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 $as_echo "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 $as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} as_fn_error "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## ## -------------------- ## ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu # Export variables LIBVER=1 LIBREV=0 TARGETS="all" MYJAVAHOME="/usr/java" JVMPLATFORM="linux" JAVAC="javac" JAR="jar" JAVAH="javah" JAVADOC="javadoc" JAVARUN="java" MYDEFS="" MYOPTS="" LD="ld" # Building paths pathtmp="$PATH" PATH="$HOME/bin:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin" PATH="$PATH:/usr/ccs/bin:/usr/ucb:/usr/xpg4/bin:/usr/xpg6/bin:$pathtmp" LIBRARY_PATH="$HOME/lib:/usr/local/lib:$LIBRARY_PATH" LD_LIBRARY_PATH="$HOME/lib:/usr/local/lib:$LD_LIBRARY_PATH" CPATH="$HOME/include:/usr/local/include:$CPATH" export PATH LIBRARY_PATH LD_LIBRARY_PATH CPATH #================================================================ # Options #================================================================ # Debug mode # Check whether --enable-debug was given. if test "${enable_debug+set}" = set; then : enableval=$enable_debug; fi if test "$enable_debug" = "yes" then TARGETS="debug" fi # Developping mode # Check whether --enable-devel was given. if test "${enable_devel+set}" = set; then : enableval=$enable_devel; fi if test "$enable_devel" = "yes" then TARGETS="devel" fi # Enable gcj # Check whether --with-gcj was given. if test "${with_gcj+set}" = set; then : withval=$with_gcj; fi #================================================================ # Checking Commands to Build with #================================================================ # Home directory of Java printf 'checking MYJAVAHOME... ' if test -d "$JAVA_HOME" then MYJAVAHOME="$JAVA_HOME" fi printf '%s\n' "$MYJAVAHOME" # Platform of Java printf 'checking JVMPLATFORM... ' if uname | grep Darwin > /dev/null then JVMPLATFORM="mac" else for file in `\ls $MYJAVAHOME/include` do if test -d "$MYJAVAHOME/include/$file" then JVMPLATFORM="$file" fi done fi printf '%s\n' "$JVMPLATFORM" # Java compiler printf 'checking JAVAC... ' JAVAC="$MYJAVAHOME/bin/javac" if uname | grep Darwin > /dev/null then if test -x "$MYJAVAHOME/Commands/javac" then JAVAC="$MYJAVAHOME/Commands/javac" else JAVAC="$MYJAVAHOME/bin/javac" fi fi if test "$with_gcj" = "yes" then JAVAC="gcj -C -Wall" printf 'gcj -C -Wall\n' elif test -x "$JAVAC" then printf '%s\n' "$JAVAC" else printf 'no\n' printf '#================================================================\n' 1>&2 printf '# WARNING: %s is not found.\n' "$JAVAC" 1>&2 printf '#================================================================\n' 1>&2 fi # Other building tools if test "$with_gcj" = "yes" then JAR="jar" JAVAH="gcjh" JAVADOC="false" JAVARUN="gij" elif uname | grep Darwin > /dev/null then if test -x "$MYJAVAHOME/Commands/java" then JAR="$MYJAVAHOME/Commands/jar" JAVAH="$MYJAVAHOME/Commands/javah" JAVADOC="$MYJAVAHOME/Commands/javadoc" JAVARUN="$MYJAVAHOME/Commands/java" else JAR="$MYJAVAHOME/bin/jar" JAVAH="$MYJAVAHOME/bin/javah" JAVADOC="$MYJAVAHOME/bin/javadoc" JAVARUN="$MYJAVAHOME/bin/java" fi else JAR="$MYJAVAHOME/bin/jar" JAVAH="$MYJAVAHOME/bin/javah" JAVADOC="$MYJAVAHOME/bin/javadoc" JAVARUN="$MYJAVAHOME/bin/java" fi # C compiler ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_CC+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_ac_ct_CC+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_CC+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_CC+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_CC+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_ac_ct_CC+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error "no acceptable C compiler found in \$PATH See \`config.log' for more details." "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 $as_echo_n "checking whether the C compiler works... " >&6; } ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # The possible output files: ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { { ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link_default") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an `-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else ac_file='' fi if test -z "$ac_file"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { as_fn_set_status 77 as_fn_error "C compiler cannot create executables See \`config.log' for more details." "$LINENO" 5; }; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 $as_echo_n "checking for C compiler default output file name... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 $as_echo "$ac_file" >&6; } ac_exeext=$ac_cv_exeext rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 $as_echo_n "checking for suffix of executables... " >&6; } if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error "cannot compute suffix of executables: cannot compile and link See \`config.log' for more details." "$LINENO" 5; } fi rm -f conftest conftest$ac_cv_exeext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 $as_echo "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { FILE *f = fopen ("conftest.out", "w"); return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF ac_clean_files="$ac_clean_files conftest.out" # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 $as_echo_n "checking whether we are cross compiling... " >&6; } if test "$cross_compiling" != yes; then { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if { ac_try='./conftest$ac_cv_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error "cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details." "$LINENO" 5; } fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 $as_echo "$cross_compiling" >&6; } rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 $as_echo_n "checking for suffix of object files... " >&6; } if test "${ac_cv_objext+set}" = set; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error "cannot compute suffix of object files: cannot compile See \`config.log' for more details." "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 $as_echo "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if test "${ac_cv_c_compiler_gnu+set}" = set; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if test "${ac_cv_prog_cc_g+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if test "${ac_cv_prog_cc_c89+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test "$GCC" != "yes" then printf '#================================================================\n' 1>&2 printf '# WARNING: GCC is required to build this package.\n' 1>&2 printf '#================================================================\n' 1>&2 fi if uname | egrep -i 'SunOS' > /dev/null 2>&1 then MYOPTS="-O1" fi if uname | egrep -i 'BSD' > /dev/null 2>&1 then MYOPTS="-O1" fi if gcc --version | egrep -i '^2\.(8|9)' > /dev/null 2>&1 then MYOPTS="-O1" fi # Linker printf 'checking for ld... ' if which ld | grep '/ld$' > /dev/null 2>&1 then LD=`which ld` printf '%s\n' "$LD" else printf 'no\n' printf '#================================================================\n' 1>&2 printf '# WARNING: ld is not found in PATH.\n' 1>&2 printf '#================================================================\n' 1>&2 fi #================================================================ # Checking Libraries #================================================================ # Underlying libraries { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lc" >&5 $as_echo_n "checking for main in -lc... " >&6; } if test "${ac_cv_lib_c_main+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lc $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_c_main=yes else ac_cv_lib_c_main=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_c_main" >&5 $as_echo "$ac_cv_lib_c_main" >&6; } if test "x$ac_cv_lib_c_main" = x""yes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBC 1 _ACEOF LIBS="-lc $LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lpthread" >&5 $as_echo_n "checking for main in -lpthread... " >&6; } if test "${ac_cv_lib_pthread_main+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lpthread $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_pthread_main=yes else ac_cv_lib_pthread_main=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_main" >&5 $as_echo "$ac_cv_lib_pthread_main" >&6; } if test "x$ac_cv_lib_pthread_main" = x""yes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBPTHREAD 1 _ACEOF LIBS="-lpthread $LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lz" >&5 $as_echo_n "checking for main in -lz... " >&6; } if test "${ac_cv_lib_z_main+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lz $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_z_main=yes else ac_cv_lib_z_main=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_z_main" >&5 $as_echo "$ac_cv_lib_z_main" >&6; } if test "x$ac_cv_lib_z_main" = x""yes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBZ 1 _ACEOF LIBS="-lz $LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -llzo2" >&5 $as_echo_n "checking for main in -llzo2... " >&6; } if test "${ac_cv_lib_lzo2_main+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-llzo2 $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_lzo2_main=yes else ac_cv_lib_lzo2_main=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_lzo2_main" >&5 $as_echo "$ac_cv_lib_lzo2_main" >&6; } if test "x$ac_cv_lib_lzo2_main" = x""yes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBLZO2 1 _ACEOF LIBS="-llzo2 $LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lbz2" >&5 $as_echo_n "checking for main in -lbz2... " >&6; } if test "${ac_cv_lib_bz2_main+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lbz2 $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_bz2_main=yes else ac_cv_lib_bz2_main=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_bz2_main" >&5 $as_echo "$ac_cv_lib_bz2_main" >&6; } if test "x$ac_cv_lib_bz2_main" = x""yes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBBZ2 1 _ACEOF LIBS="-lbz2 $LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -liconv" >&5 $as_echo_n "checking for main in -liconv... " >&6; } if test "${ac_cv_lib_iconv_main+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-liconv $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_iconv_main=yes else ac_cv_lib_iconv_main=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_iconv_main" >&5 $as_echo "$ac_cv_lib_iconv_main" >&6; } if test "x$ac_cv_lib_iconv_main" = x""yes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBICONV 1 _ACEOF LIBS="-liconv $LIBS" fi # Fundamental QDBM libraries { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lqdbm" >&5 $as_echo_n "checking for main in -lqdbm... " >&6; } if test "${ac_cv_lib_qdbm_main+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lqdbm $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_qdbm_main=yes else ac_cv_lib_qdbm_main=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_qdbm_main" >&5 $as_echo "$ac_cv_lib_qdbm_main" >&6; } if test "x$ac_cv_lib_qdbm_main" = x""yes; then : true else printf 'checking whether /usr/local/lib/libqdbm.* is... ' if ls /usr/local/lib/libqdbm.* > /dev/null 2>&1 then printf 'yes\n' else printf 'no\n' printf '#================================================================\n' 1>&2 printf '# WARNING: Install QDBM libraries before installation.\n' 1>&2 printf '#================================================================\n' 1>&2 fi fi # For old BSDs if uname -a | grep BSD > /dev/null && test -f /usr/lib/libc_r.a && test ! -f /usr/lib/libpthread.a then LIBS=`printf '%s' "$LIBS" | sed 's/-lc/-lc_r/g'` fi # Duplication of QDBM for Java { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -ljqdbm" >&5 $as_echo_n "checking for main in -ljqdbm... " >&6; } if test "${ac_cv_lib_jqdbm_main+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ljqdbm $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_jqdbm_main=yes else ac_cv_lib_jqdbm_main=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_jqdbm_main" >&5 $as_echo "$ac_cv_lib_jqdbm_main" >&6; } if test "x$ac_cv_lib_jqdbm_main" = x""yes; then : printf '#================================================================\n' 1>&2 printf '# WARNING: An old library was detected.\n' 1>&2 printf '#================================================================\n' 1>&2 fi #================================================================ # Generic Settings #================================================================ # Data types if uname | grep '^SunOS' > /dev/null then MYDEFS='-Dint64_t=long\ long' elif uname | grep '^CYGWIN' > /dev/null then MYDEFS='-D__int64=long\ long' fi # Export variables # Targets ac_config_files="$ac_config_files Makefile" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then test "x$cache_file" != "x/dev/null" && { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} cat confcache >$cache_file else { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' # Transform confdefs.h into DEFS. # Protect against shell expansion while executing Makefile rules. # Protect against Makefile macro expansion. # # If the first sed substitution is executed (which looks for macros that # take arguments), then branch to the quote section. Otherwise, # look for a macro that doesn't take arguments. ac_script=' :mline /\\$/{ N s,\\\n,, b mline } t clear :clear s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g t quote s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g t quote b any :quote s/[ `~#$^&*(){}\\|;'\''"<>?]/\\&/g s/\[/\\&/g s/\]/\\&/g s/\$/$$/g H :any ${ g s/^\n// s/\n/ /g p } ' DEFS=`sed -n "$ac_script" confdefs.h` ac_libobjs= ac_ltlibobjs= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`$as_echo "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs : ${CONFIG_STATUS=./config.status} ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 $as_echo "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # as_fn_error ERROR [LINENO LOG_FD] # --------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with status $?, using 1 if that was 0. as_fn_error () { as_status=$?; test $as_status -eq 0 && as_status=1 if test "$3"; then as_lineno=${as_lineno-"$2"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $1" >&$3 fi $as_echo "$as_me: error: $1" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -p'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -p' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -p' fi else as_ln_s='cp -p' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi if test -x / >/dev/null 2>&1; then as_test_x='test -x' else if ls -dL / >/dev/null 2>&1; then as_ls_L_option=L else as_ls_L_option= fi as_test_x=' eval sh -c '\'' if test -d "$1"; then test -d "$1/."; else case $1 in #( -*)set "./$1";; esac; case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( ???[sx]*):;;*)false;;esac;fi '\'' sh ' fi as_executable_p=$as_test_x # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 ## ----------------------------------- ## ## Main body of $CONFIG_STATUS script. ## ## ----------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by qdbm-java $as_me 1.0.0, which was generated by GNU Autoconf 2.65. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ \`$as_me' instantiates files and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit --config print configuration, then exit -q, --quiet, --silent do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE Configuration files: $config_files Report bugs to the package provider." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ qdbm-java config.status 1.0.0 configured by $0, generated by GNU Autoconf 2.65, with options \\"\$ac_cs_config\\" Copyright (C) 2009 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) $as_echo "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) $as_echo "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --he | --h | --help | --hel | -h ) $as_echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) as_fn_error "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX $as_echo "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; *) as_fn_error "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= trap 'exit_status=$? { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error "cannot create a temporary directory in ." "$LINENO" 5 # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with `./config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=`echo X | tr X '\015'` # On cygwin, bash can eat \r inside `` if the user requested igncr. # But we know of no other shell where ac_cr would be empty at this # point, so we can use a bashism as a fallback. if test "x$ac_cr" = x; then eval ac_cr=\$\'\\r\' fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_num=`echo "$ac_subst_vars" | grep -c '$'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>"\$tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\)..*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\)..*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' >$CONFIG_STATUS || ac_write_fail=1 rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$tmp/subs1.awk" > "$tmp/subs.awk" \ || as_fn_error "could not setup config files machinery" "$LINENO" 5 _ACEOF # VPATH may cause trouble with some makes, so we remove $(srcdir), # ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=/{ s/:*\$(srcdir):*/:/ s/:*\${srcdir}:*/:/ s/:*@srcdir@:*/:/ s/^\([^=]*=[ ]*\):*/\1/ s/:*$// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" eval set X " :F $CONFIG_FILES " shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) as_fn_error "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || as_fn_error "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 $as_echo "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`$as_echo "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$tmp/stdin" \ || as_fn_error "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 $as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$tmp/subs.awk" >$tmp/out \ || as_fn_error "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } && { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined." >&5 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined." >&2;} rm -f "$tmp/stdin" case $ac_file in -) cat "$tmp/out" && rm -f "$tmp/out";; *) rm -f "$ac_file" && mv "$tmp/out" "$ac_file";; esac \ || as_fn_error "could not create $ac_file" "$LINENO" 5 ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || as_fn_error "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit $? fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi # END OF FILE qdbm-1.8.78/vista.c0000644000175000017500000000660310610627747013055 0ustar mikiomikio/************************************************************************************************* * Implementation of Vista * Copyright (C) 2000-2007 Mikio Hirabayashi * This file is part of QDBM, Quick Database Manager. * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU * Lesser General Public License as published by the Free Software Foundation; either version * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * You should have received a copy of the GNU Lesser General Public License along with QDBM; if * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. *************************************************************************************************/ #define QDBM_INTERNAL 1 #define _VISTA_C 1 #include "vista.h" #include "myconf.h" /************************************************************************************************* * macros to convert Depot to Curia *************************************************************************************************/ #define DEPOT CURIA #define \ dpopen(name, omode, bnum) \ cropen(name, omode, ((bnum / vlcrdnum) * 2), vlcrdnum) #define \ dpclose(db) \ crclose(db) #define \ dpput(db, kbuf, ksiz, vbuf, vsiz, dmode) \ crput(db, kbuf, ksiz, vbuf, vsiz, dmode) #define \ dpout(db, kbuf, ksiz) \ crout(db, kbuf, ksiz) #define \ dpget(db, kbuf, ksiz, start, max, sp) \ crget(db, kbuf, ksiz, start, max, sp) #define \ dpgetwb(db, kbuf, ksiz, start, max, vbuf) \ crgetwb(db, kbuf, ksiz, start, max, vbuf) #define \ dpvsiz(db, kbuf, ksiz) \ crvsiz(db, kbuf, ksiz) #define \ dpiterinit(db) \ criterinit(db) #define \ dpiternext(db, sp) \ criternext(db, sp) #define \ dpsetalign(db, align) \ crsetalign(db, align) #define \ dpsetfbpsiz(db, size) \ crsetfbpsiz(db, size) #define \ dpsync(db) \ crsync(db) #define \ dpoptimize(db, bnum) \ croptimize(db, bnum) #define \ dpname(db) \ crname(db) #define \ dpfsiz(db) \ crfsiz(db) #define \ dpbnum(db) \ crbnum(db) #define \ dpbusenum(db) \ crbusenum(db) #define \ dprnum(db) \ crrnum(db) #define \ dpwritable(db) \ crwritable(db) #define \ dpfatalerror(db) \ crfatalerror(db) #define \ dpinode(db) \ crinode(db) #define \ dpmtime(db) \ crmtime(db) #define \ dpfdesc(db) \ crfdesc(db) #define \ dpremove(db) \ crremove(db) #define \ dprepair(db) \ crrepair(db) #define \ dpexportdb(db, name) \ crexportdb(db, name) #define \ dpimportdb(db, name) \ crimportdb(db, name) #define \ dpsnaffle(db, name) \ crsnaffle(db, name) #define \ dpmemsync(db) \ crmemsync(db) #define \ dpmemflush(db) \ crmemflush(db) #define \ dpgetflags(db) \ crgetflags(db) #define \ dpsetflags(db, flags) \ crsetflags(db, flags) /************************************************************************************************* * including real implementation *************************************************************************************************/ #include "villa.c" /* END OF FILE */ qdbm-1.8.78/vlmgr.c0000644000175000017500000005443610610627747013065 0ustar mikiomikio/************************************************************************************************* * Utility for debugging Villa and its applications * Copyright (C) 2000-2007 Mikio Hirabayashi * This file is part of QDBM, Quick Database Manager. * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU * Lesser General Public License as published by the Free Software Foundation; either version * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * You should have received a copy of the GNU Lesser General Public License along with QDBM; if * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. *************************************************************************************************/ #include #include #include #include #include #include #undef TRUE #define TRUE 1 /* boolean true */ #undef FALSE #define FALSE 0 /* boolean false */ /* for RISC OS */ #if defined(__riscos__) || defined(__riscos) #include int __riscosify_control = __RISCOSIFY_NO_PROCESS; #endif /* global variables */ const char *progname; /* program name */ /* function prototypes */ int main(int argc, char **argv); void usage(void); char *hextoobj(const char *str, int *sp); char *dectoiobj(const char *str, int *sp); int runcreate(int argc, char **argv); int runput(int argc, char **argv); int runout(int argc, char **argv); int runget(int argc, char **argv); int runlist(int argc, char **argv); int runoptimize(int argc, char **argv); int runinform(int argc, char **argv); int runremove(int argc, char **argv); int runrepair(int argc, char **argv); int runexportdb(int argc, char **argv); int runimportdb(int argc, char **argv); void pdperror(const char *name); void printobj(const char *obj, int size); void printobjhex(const char *obj, int size); int docreate(const char *name, int cmode); int doput(const char *name, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int dmode, VLCFUNC cmp); int doout(const char *name, const char *kbuf, int ksiz, VLCFUNC cmp, int lb); int doget(const char *name, int opts, const char *kbuf, int ksiz, VLCFUNC cmp, int lb, int ox, int nb); int dolist(const char *name, int opts, const char *tbuf, int tsiz, const char *bbuf, int bsiz, VLCFUNC cmp, int ki, int kb, int vb, int ox, int gt, int lt, int max, int desc); int dooptimize(const char *name); int doinform(const char *name, int opts); int doremove(const char *name); int dorepair(const char *name, VLCFUNC cmp); int doexportdb(const char *name, const char *file, VLCFUNC cmp); int doimportdb(const char *name, const char *file, VLCFUNC cmp); /* main routine */ int main(int argc, char **argv){ char *env; int rv; cbstdiobin(); progname = argv[0]; if((env = getenv("QDBMDBGFD")) != NULL) dpdbgfd = atoi(env); if(argc < 2) usage(); rv = 0; if(!strcmp(argv[1], "create")){ rv = runcreate(argc, argv); } else if(!strcmp(argv[1], "put")){ rv = runput(argc, argv); } else if(!strcmp(argv[1], "out")){ rv = runout(argc, argv); } else if(!strcmp(argv[1], "get")){ rv = runget(argc, argv); } else if(!strcmp(argv[1], "list")){ rv = runlist(argc, argv); } else if(!strcmp(argv[1], "optimize")){ rv = runoptimize(argc, argv); } else if(!strcmp(argv[1], "inform")){ rv = runinform(argc, argv); } else if(!strcmp(argv[1], "remove")){ rv = runremove(argc, argv); } else if(!strcmp(argv[1], "repair")){ rv = runrepair(argc, argv); } else if(!strcmp(argv[1], "exportdb")){ rv = runexportdb(argc, argv); } else if(!strcmp(argv[1], "importdb")){ rv = runimportdb(argc, argv); } else if(!strcmp(argv[1], "version") || !strcmp(argv[1], "--version")){ printf("Powered by QDBM version %s on %s%s\n", dpversion, dpsysname, dpisreentrant ? " (reentrant)" : ""); printf("Copyright (c) 2000-2007 Mikio Hirabayashi\n"); rv = 0; } else { usage(); } return rv; } /* print the usage and exit */ void usage(void){ fprintf(stderr, "%s: administration utility for Villa\n", progname); fprintf(stderr, "\n"); fprintf(stderr, "usage:\n"); fprintf(stderr, " %s create [-cz|-cy|-cx] name\n", progname); fprintf(stderr, " %s put [-kx|-ki] [-vx|-vi|-vf] [-keep|-cat|-dup] name key val\n", progname); fprintf(stderr, " %s out [-l] [-kx|-ki] name key\n", progname); fprintf(stderr, " %s get [-nl] [-l] [-kx|-ki] [-ox] [-n] name key\n", progname); fprintf(stderr, " %s list [-nl] [-k|-v] [-kx|-ki] [-ox] [-top key] [-bot key] [-gt] [-lt]" " [-max num] [-desc] name\n", progname); fprintf(stderr, " %s optimize name\n", progname); fprintf(stderr, " %s inform [-nl] name\n", progname); fprintf(stderr, " %s remove name\n", progname); fprintf(stderr, " %s repair [-ki] name\n", progname); fprintf(stderr, " %s exportdb [-ki] name file\n", progname); fprintf(stderr, " %s importdb [-ki] name file\n", progname); fprintf(stderr, " %s version\n", progname); fprintf(stderr, "\n"); exit(1); } /* create a binary object from a hexadecimal string */ char *hextoobj(const char *str, int *sp){ char *buf, mbuf[3]; int len, i, j; len = strlen(str); if(!(buf = malloc(len + 1))) return NULL; j = 0; for(i = 0; i < len; i += 2){ while(strchr(" \n\r\t\f\v", str[i])){ i++; } if((mbuf[0] = str[i]) == '\0') break; if((mbuf[1] = str[i+1]) == '\0') break; mbuf[2] = '\0'; buf[j++] = (char)strtol(mbuf, NULL, 16); } buf[j] = '\0'; *sp = j; return buf; } /* create a integer object from a decimal string */ char *dectoiobj(const char *str, int *sp){ char *buf; int num; num = atoi(str); if(!(buf = malloc(sizeof(int)))) return NULL; *(int *)buf = num; *sp = sizeof(int); return buf; } /* parse arguments of create command */ int runcreate(int argc, char **argv){ char *name; int i, cmode, rv; name = NULL; cmode = 0; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ if(!strcmp(argv[i], "-cz")){ cmode |= VL_OZCOMP; } else if(!strcmp(argv[i], "-cy")){ cmode |= VL_OYCOMP; } else if(!strcmp(argv[i], "-cx")){ cmode |= VL_OXCOMP; } else { usage(); } } else if(!name){ name = argv[i]; } else { usage(); } } if(!name) usage(); rv = docreate(name, cmode); return rv; } /* parse arguments of put command */ int runput(int argc, char **argv){ char *name, *key, *val, *kbuf, *vbuf; int i, kx, ki, vx, vi, vf, ksiz, vsiz, rv; int dmode; name = NULL; kx = FALSE; ki = FALSE; vx = FALSE; vi = FALSE; vf = FALSE; key = NULL; val = NULL; dmode = VL_DOVER; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ if(!strcmp(argv[i], "-kx")){ kx = TRUE; } else if(!strcmp(argv[i], "-ki")){ ki = TRUE; } else if(!strcmp(argv[i], "-vx")){ vx = TRUE; } else if(!strcmp(argv[i], "-vi")){ vi = TRUE; } else if(!strcmp(argv[i], "-vf")){ vf = TRUE; } else if(!strcmp(argv[i], "-keep")){ dmode = VL_DKEEP; } else if(!strcmp(argv[i], "-cat")){ dmode = VL_DCAT; } else if(!strcmp(argv[i], "-dup")){ dmode = VL_DDUP; } else { usage(); } } else if(!name){ name = argv[i]; } else if(!key){ key = argv[i]; } else if(!val){ val = argv[i]; } else { usage(); } } if(!name || !key || !val) usage(); if(kx){ kbuf = hextoobj(key, &ksiz); } else if(ki){ kbuf = dectoiobj(key, &ksiz); } else { kbuf = cbmemdup(key, -1); ksiz = -1; } if(vx){ vbuf = hextoobj(val, &vsiz); } else if(vi){ vbuf = dectoiobj(val, &vsiz); } else if(vf){ vbuf = cbreadfile(val, &vsiz); } else { vbuf = cbmemdup(val, -1); vsiz = -1; } if(kbuf && vbuf){ rv = doput(name, kbuf, ksiz, vbuf, vsiz, dmode, ki ? VL_CMPINT : VL_CMPLEX); } else { if(vf){ fprintf(stderr, "%s: %s: cannot read\n", progname, val); } else { fprintf(stderr, "%s: out of memory\n", progname); } rv = 1; } free(kbuf); free(vbuf); return rv; } /* parse arguments of out command */ int runout(int argc, char **argv){ char *name, *key, *kbuf; int i, kx, ki, lb, ksiz, rv; name = NULL; kx = FALSE; ki = FALSE; lb = FALSE; key = NULL; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ if(!strcmp(argv[i], "-l")){ lb = TRUE; } else if(!strcmp(argv[i], "-kx")){ kx = TRUE; } else if(!strcmp(argv[i], "-ki")){ ki = TRUE; } else { usage(); } } else if(!name){ name = argv[i]; } else if(!key){ key = argv[i]; } else { usage(); } } if(!name || !key) usage(); if(kx){ kbuf = hextoobj(key, &ksiz); } else if(ki){ kbuf = dectoiobj(key, &ksiz); } else { kbuf = cbmemdup(key, -1); ksiz = -1; } if(kbuf){ rv = doout(name, kbuf, ksiz, ki ? VL_CMPINT : VL_CMPLEX, lb); } else { fprintf(stderr, "%s: out of memory\n", progname); rv = 1; } free(kbuf); return rv; } /* parse arguments of get command */ int runget(int argc, char **argv){ char *name, *key, *kbuf; int i, opts, lb, kx, ki, ox, nb, ksiz, rv; name = NULL; opts = 0; lb = FALSE; kx = FALSE; ki = FALSE; ox = FALSE; nb = FALSE; key = NULL; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ if(!strcmp(argv[i], "-nl")){ opts |= VL_ONOLCK; } else if(!strcmp(argv[i], "-l")){ lb = TRUE; } else if(!strcmp(argv[i], "-kx")){ kx = TRUE; } else if(!strcmp(argv[i], "-ki")){ ki = TRUE; } else if(!strcmp(argv[i], "-ox")){ ox = TRUE; } else if(!strcmp(argv[i], "-n")){ nb = TRUE; } else { usage(); } } else if(!name){ name = argv[i]; } else if(!key){ key = argv[i]; } else { usage(); } } if(!name || !key) usage(); if(kx){ kbuf = hextoobj(key, &ksiz); } else if(ki){ kbuf = dectoiobj(key, &ksiz); } else { kbuf = cbmemdup(key, -1); ksiz = -1; } if(kbuf){ rv = doget(name, opts, kbuf, ksiz, ki ? VL_CMPINT : VL_CMPLEX, lb, ox, nb); } else { fprintf(stderr, "%s: out of memory\n", progname); rv = 1; } free(kbuf); return rv; } /* parse arguments of list command */ int runlist(int argc, char **argv){ char *name, *top, *bot, *tbuf, *bbuf, *nstr; int i, opts, kb, vb, kx, ki, ox, gt, lt, max, desc, tsiz, bsiz, rv; name = NULL; opts = 0; kb = FALSE; vb = FALSE; kx = FALSE; ki = FALSE; ox = FALSE; gt = FALSE; lt = FALSE; max = -1; desc = FALSE; top = NULL; bot = NULL; nstr = NULL; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ if(!strcmp(argv[i], "-nl")){ opts |= VL_ONOLCK; } else if(!strcmp(argv[i], "-k")){ kb = TRUE; } else if(!strcmp(argv[i], "-v")){ vb = TRUE; } else if(!strcmp(argv[i], "-kx")){ kx = TRUE; } else if(!strcmp(argv[i], "-ki")){ ki = TRUE; } else if(!strcmp(argv[i], "-ox")){ ox = TRUE; } else if(!strcmp(argv[i], "-top")){ if(++i >= argc) usage(); top = argv[i]; } else if(!strcmp(argv[i], "-bot")){ if(++i >= argc) usage(); bot = argv[i]; } else if(!strcmp(argv[i], "-gt")){ gt = TRUE; } else if(!strcmp(argv[i], "-lt")){ lt = TRUE; } else if(!strcmp(argv[i], "-max")){ if(++i >= argc) usage(); max = atoi(argv[i]); } else if(!strcmp(argv[i], "-desc")){ desc = TRUE; } else { usage(); } } else if(!name){ name = argv[i]; } else { usage(); } } if(!name) usage(); tbuf = NULL; bbuf = NULL; if(kx){ if(top) tbuf = hextoobj(top, &tsiz); if(bot) bbuf = hextoobj(bot, &bsiz); } else if(ki){ if(top) tbuf = dectoiobj(top, &tsiz); if(bot) bbuf = dectoiobj(bot, &bsiz); } else { if(top){ tbuf = cbmemdup(top, -1); tsiz = strlen(tbuf); } if(bot){ bbuf = cbmemdup(bot, -1); bsiz = strlen(bbuf); } } rv = dolist(name, opts, tbuf, tsiz, bbuf, bsiz, ki ? VL_CMPINT : VL_CMPLEX, ki, kb, vb, ox, gt, lt, max, desc); free(tbuf); free(bbuf); return rv; } /* parse arguments of optimize command */ int runoptimize(int argc, char **argv){ char *name; int i, rv; name = NULL; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ usage(); } else if(!name){ name = argv[i]; } else { usage(); } } if(!name) usage(); rv = dooptimize(name); return rv; } /* parse arguments of inform command */ int runinform(int argc, char **argv){ char *name; int i, opts, rv; name = NULL; opts = 0; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ if(!strcmp(argv[i], "-nl")){ opts |= VL_ONOLCK; } else { usage(); } } else if(!name){ name = argv[i]; } else { usage(); } } if(!name) usage(); rv = doinform(name, opts); return rv; } /* parse arguments of remove command */ int runremove(int argc, char **argv){ char *name; int i, rv; name = NULL; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ usage(); } else if(!name){ name = argv[i]; } else { usage(); } } if(!name) usage(); rv = doremove(name); return rv; } /* parse arguments of repair command */ int runrepair(int argc, char **argv){ char *name; int i, ki, rv; name = NULL; ki = FALSE; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ if(!strcmp(argv[i], "-ki")){ ki = TRUE; } else { usage(); } } else if(!name){ name = argv[i]; } else { usage(); } } if(!name) usage(); rv = dorepair(name, ki ? VL_CMPINT : VL_CMPLEX); return rv; } /* parse arguments of exportdb command */ int runexportdb(int argc, char **argv){ char *name, *file; int i, ki, rv; name = NULL; file = NULL; ki = FALSE; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ if(!strcmp(argv[i], "-ki")){ ki = TRUE; } else { usage(); } } else if(!name){ name = argv[i]; } else if(!file){ file = argv[i]; } else { usage(); } } if(!name || !file) usage(); rv = doexportdb(name, file, ki ? VL_CMPINT : VL_CMPLEX); return rv; } /* parse arguments of importdb command */ int runimportdb(int argc, char **argv){ char *name, *file; int i, ki, rv; name = NULL; file = NULL; ki = FALSE; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ if(!strcmp(argv[i], "-ki")){ ki = TRUE; } else { usage(); } } else if(!name){ name = argv[i]; } else if(!file){ file = argv[i]; } else { usage(); } } if(!name || !file) usage(); rv = doimportdb(name, file, ki ? VL_CMPINT : VL_CMPLEX); return rv; } /* print an error message */ void pdperror(const char *name){ fprintf(stderr, "%s: %s: %s\n", progname, name, dperrmsg(dpecode)); } /* print an object */ void printobj(const char *obj, int size){ int i; for(i = 0; i < size; i++){ putchar(obj[i]); } } /* print an object as a hexadecimal string */ void printobjhex(const char *obj, int size){ int i; for(i = 0; i < size; i++){ printf("%s%02X", i > 0 ? " " : "", ((const unsigned char *)obj)[i]); } } /* perform create command */ int docreate(const char *name, int cmode){ VILLA *villa; int omode; omode = VL_OWRITER | VL_OCREAT | VL_OTRUNC | cmode; if(!(villa = vlopen(name, omode, VL_CMPLEX))){ pdperror(name); return 1; } if(!vlclose(villa)){ pdperror(name); return 1; } return 0; } /* perform put command */ int doput(const char *name, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int dmode, VLCFUNC cmp){ VILLA *villa; if(!(villa = vlopen(name, VL_OWRITER, cmp))){ pdperror(name); return 1; } if(!vlput(villa, kbuf, ksiz, vbuf, vsiz, dmode)){ pdperror(name); vlclose(villa); return 1; } if(!vlclose(villa)){ pdperror(name); return 1; } return 0; } /* perform out command */ int doout(const char *name, const char *kbuf, int ksiz, VLCFUNC cmp, int lb){ VILLA *villa; if(!(villa = vlopen(name, VL_OWRITER, cmp))){ pdperror(name); return 1; } if(lb){ if(!vloutlist(villa, kbuf, ksiz)){ pdperror(name); vlclose(villa); return 1; } } else { if(!vlout(villa, kbuf, ksiz)){ pdperror(name); vlclose(villa); return 1; } } if(!vlclose(villa)){ pdperror(name); return 1; } return 0; } /* perform get command */ int doget(const char *name, int opts, const char *kbuf, int ksiz, VLCFUNC cmp, int lb, int ox, int nb){ VILLA *villa; CBLIST *vals; char *vbuf; int vsiz; if(!(villa = vlopen(name, VL_OREADER | opts, cmp))){ pdperror(name); return 1; } if(lb){ if(!(vals = vlgetlist(villa, kbuf, ksiz))){ pdperror(name); vlclose(villa); return 1; } while((vbuf = cblistshift(vals, &vsiz)) != NULL){ if(ox){ printobjhex(vbuf, vsiz); } else { printobj(vbuf, vsiz); } free(vbuf); putchar('\n'); } cblistclose(vals); } else { if(!(vbuf = vlget(villa, kbuf, ksiz, &vsiz))){ pdperror(name); vlclose(villa); return 1; } if(ox){ printobjhex(vbuf, vsiz); } else { printobj(vbuf, vsiz); } free(vbuf); if(!nb) putchar('\n'); } if(!vlclose(villa)){ pdperror(name); return 1; } return 0; } /* perform list command */ int dolist(const char *name, int opts, const char *tbuf, int tsiz, const char *bbuf, int bsiz, VLCFUNC cmp, int ki, int kb, int vb, int ox, int gt, int lt, int max, int desc){ VILLA *villa; char *kbuf, *vbuf; int ksiz, vsiz, show, rv; if(!(villa = vlopen(name, VL_OREADER | opts, cmp))){ pdperror(name); return 1; } if(max < 0) max = vlrnum(villa); if(desc){ if(bbuf){ vlcurjump(villa, bbuf, bsiz, VL_JBACKWARD); } else { vlcurlast(villa); } show = 0; while(show < max && (kbuf = vlcurkey(villa, &ksiz)) != NULL){ if(bbuf && lt){ if(cmp(kbuf, ksiz, bbuf, bsiz) == 0){ free(kbuf); vlcurnext(villa); continue; } lt = FALSE; } if(tbuf){ rv = cmp(kbuf, ksiz, tbuf, tsiz); if(rv < 0 || (gt && rv == 0)){ free(kbuf); break; } } if(!(vbuf = vlcurval(villa, &vsiz))){ free(kbuf); break; } if(ox){ if(!vb) printobjhex(kbuf, ksiz); if(!kb && !vb) putchar('\t'); if(!kb) printobjhex(vbuf, vsiz); } else { if(!vb) printobj(kbuf, ksiz); if(!kb && !vb) putchar('\t'); if(!kb) printobj(vbuf, vsiz); } putchar('\n'); free(kbuf); free(vbuf); show++; vlcurprev(villa); } } else { if(tbuf){ vlcurjump(villa, tbuf, tsiz, VL_JFORWARD); } else { vlcurfirst(villa); } show = 0; while(show < max && (kbuf = vlcurkey(villa, &ksiz)) != NULL){ if(tbuf && gt){ if(cmp(kbuf, ksiz, tbuf, tsiz) == 0){ free(kbuf); vlcurnext(villa); continue; } gt = FALSE; } if(bbuf){ rv = cmp(kbuf, ksiz, bbuf, bsiz); if(rv > 0 || (lt && rv == 0)){ free(kbuf); break; } } if(!(vbuf = vlcurval(villa, &vsiz))){ free(kbuf); break; } if(ox){ if(!vb) printobjhex(kbuf, ksiz); if(!kb && !vb) putchar('\t'); if(!kb) printobjhex(vbuf, vsiz); } else { if(!vb) printobj(kbuf, ksiz); if(!kb && !vb) putchar('\t'); if(!kb) printobj(vbuf, vsiz); } putchar('\n'); free(kbuf); free(vbuf); show++; vlcurnext(villa); } } if(!vlclose(villa)){ pdperror(name); return 1; } return 0; } /* perform optimize command */ int dooptimize(const char *name){ VILLA *villa; if(!(villa = vlopen(name, VL_OWRITER, VL_CMPLEX))){ pdperror(name); return 1; } if(!vloptimize(villa)){ pdperror(name); vlclose(villa); return 1; } if(!vlclose(villa)){ pdperror(name); return 1; } return 0; } /* perform inform command */ int doinform(const char *name, int opts){ VILLA *villa; char *tmp; if(!(villa = vlopen(name, VL_OREADER | opts, VL_CMPLEX))){ pdperror(name); return 1; } tmp = vlname(villa); printf("name: %s\n", tmp ? tmp : "(null)"); free(tmp); printf("file size: %d\n", vlfsiz(villa)); printf("leaf nodes: %d\n", vllnum(villa)); printf("non-leaf nodes: %d\n", vlnnum(villa)); printf("records: %d\n", vlrnum(villa)); printf("inode number: %d\n", vlinode(villa)); printf("modified time: %.0f\n", (double)vlmtime(villa)); if(!vlclose(villa)){ pdperror(name); return 1; } return 0; } /* perform remove command */ int doremove(const char *name){ if(!vlremove(name)){ pdperror(name); return 1; } return 0; } /* perform repair command */ int dorepair(const char *name, VLCFUNC cmp){ if(!vlrepair(name, cmp)){ pdperror(name); return 1; } return 0; } /* perform exportdb command */ int doexportdb(const char *name, const char *file, VLCFUNC cmp){ VILLA *villa; if(!(villa = vlopen(name, VL_OREADER, cmp))){ pdperror(name); return 1; } if(!vlexportdb(villa, file)){ pdperror(name); vlclose(villa); return 1; } if(!vlclose(villa)){ pdperror(name); return 1; } return 0; } /* perform importdb command */ int doimportdb(const char *name, const char *file, VLCFUNC cmp){ VILLA *villa; if(!(villa = vlopen(name, VL_OWRITER | VL_OCREAT | VL_OTRUNC, cmp))){ pdperror(name); return 1; } if(!vlimportdb(villa, file)){ pdperror(name); vlclose(villa); return 1; } if(!vlclose(villa)){ pdperror(name); return 1; } return 0; } /* END OF FILE */ qdbm-1.8.78/plus/0000755000175000017500000000000011426320062012523 5ustar mikiomikioqdbm-1.8.78/plus/xqdbm.cc0000644000175000017500000000302410470507403014150 0ustar mikiomikio/************************************************************************************************* * Implementation of common setting for QDBM * Copyright (C) 2000-2005 Mikio Hirabayashi * This file is part of QDBM, Quick Database Manager. * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU * Lesser General Public License as published by the Free Software Foundation; either version * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * You should have received a copy of the GNU Lesser General Public License along with QDBM; if * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. *************************************************************************************************/ #include "xqdbm.h" /************************************************************************************************* * mutex *************************************************************************************************/ pthread_mutex_t qdbm::ourmutex; namespace { class Init { public: Init(){ pthread_mutex_init(&qdbm::ourmutex, NULL); } ~Init(){ pthread_mutex_destroy(&qdbm::ourmutex); } }; Init init; } /* END OF FILE */ qdbm-1.8.78/plus/xcuria.cc0000644000175000017500000003403110505704573014340 0ustar mikiomikio/************************************************************************************************* * Implementation of Curia for C++ * Copyright (C) 2000-2005 Mikio Hirabayashi * This file is part of QDBM, Quick Database Manager. * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU * Lesser General Public License as published by the Free Software Foundation; either version * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * You should have received a copy of the GNU Lesser General Public License along with QDBM; if * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. *************************************************************************************************/ #include "xcuria.h" #include #include #include extern "C" { #include #include #include } using namespace qdbm; /************************************************************************************************* * Curia_error *************************************************************************************************/ Curia_error::Curia_error() throw() : DBM_error(){ ecode = DP_EMISC; return; } Curia_error::Curia_error(int ecode) throw() : DBM_error(){ this->ecode = ecode; return; } Curia_error::Curia_error(const Curia_error& ce) throw() : DBM_error(ce){ ecode = ce.ecode; return; } Curia_error::~Curia_error() throw(){ return; } Curia_error& Curia_error::operator =(const Curia_error& ce) throw(){ this->ecode = ce.ecode; return *this; } Curia_error& Curia_error::operator =(int ecode) throw(){ this->ecode = ecode; return *this; } bool Curia_error::operator ==(const Curia_error& ce) const throw(){ return ecode == ce.ecode; } bool Curia_error::operator !=(const Curia_error& ce) const throw(){ return ecode != ce.ecode; } bool Curia_error::operator ==(int ecode) const throw(){ return this->ecode == ecode; } bool Curia_error::operator !=(int ecode) const throw(){ return this->ecode != ecode; } Curia_error::operator const char*() const throw(){ return dperrmsg(ecode); } int Curia_error::code() const throw(){ return ecode; } const char* Curia_error::message() const throw(){ return dperrmsg(ecode); } /************************************************************************************************* * Curia *************************************************************************************************/ const int Curia::ENOERR = DP_ENOERR; const int Curia::EFATAL = DP_EFATAL; const int Curia::EMODE = DP_EMODE; const int Curia::EBROKEN = DP_EBROKEN; const int Curia::EKEEP = DP_EKEEP; const int Curia::ENOITEM = DP_ENOITEM; const int Curia::EALLOC = DP_EALLOC; const int Curia::EMAP = DP_EMAP; const int Curia::EOPEN = DP_EOPEN; const int Curia::ECLOSE = DP_ECLOSE; const int Curia::ETRUNC = DP_ETRUNC; const int Curia::ESYNC = DP_ESYNC; const int Curia::ESTAT = DP_ESTAT; const int Curia::ESEEK = DP_ESEEK; const int Curia::EREAD = DP_EREAD; const int Curia::EWRITE = DP_EWRITE; const int Curia::ELOCK = DP_ELOCK; const int Curia::EUNLINK = DP_EUNLINK; const int Curia::EMKDIR = DP_EMKDIR; const int Curia::ERMDIR = DP_ERMDIR; const int Curia::EMISC = DP_EMISC; const int Curia::OREADER = CR_OREADER; const int Curia::OWRITER = CR_OWRITER; const int Curia::OCREAT = CR_OCREAT; const int Curia::OTRUNC = CR_OTRUNC; const int Curia::ONOLCK = CR_ONOLCK; const int Curia::OLCKNB = CR_OLCKNB; const int Curia::OSPARSE = CR_OSPARSE; const int Curia::DOVER = CR_DOVER; const int Curia::DKEEP = CR_DKEEP; const int Curia::DCAT = CR_DCAT; const char* Curia::version() throw(){ return dpversion; } void Curia::remove(const char* name) throw(Curia_error){ if(pthread_mutex_lock(&ourmutex) != 0) throw Curia_error(); if(!crremove(name)){ int ecode = dpecode; pthread_mutex_unlock(&ourmutex); throw Curia_error(ecode); } pthread_mutex_unlock(&ourmutex); } char* Curia::snaffle(const char* name, const char* kbuf, int ksiz, int* sp) throw(Curia_error){ char* vbuf; if(pthread_mutex_lock(&ourmutex) != 0) throw Curia_error(); if(!(vbuf = crsnaffle(name, kbuf, ksiz, sp))){ int ecode = dpecode; pthread_mutex_unlock(&ourmutex); throw Curia_error(ecode); } pthread_mutex_unlock(&ourmutex); return vbuf; } Curia::Curia(const char* name, int omode, int bnum, int dnum) throw(Curia_error) : ADBM(){ pthread_mutex_init(&mymutex, NULL); silent = false; if(!lock()) throw Curia_error(); if(!(curia = cropen(name, omode, bnum, dnum))){ int ecode = dpecode; unlock(); throw Curia_error(ecode); } unlock(); } Curia::~Curia() throw(){ if(!curia){ pthread_mutex_destroy(&mymutex); return; } if(lock()){ crclose(curia); unlock(); } curia = 0; pthread_mutex_destroy(&mymutex); } void Curia::close() throw(Curia_error){ if(!curia) throw Curia_error(); if(!lock()) throw Curia_error(); if(!crclose(curia)){ int ecode = dpecode; curia = 0; unlock(); throw Curia_error(ecode); } curia = 0; unlock(); } bool Curia::put(const char* kbuf, int ksiz, const char* vbuf, int vsiz, int dmode) throw(Curia_error){ if(!curia) throw Curia_error(); if(!lock()) throw Curia_error(); if(!crput(curia, kbuf, ksiz, vbuf, vsiz, dmode)){ int ecode = dpecode; unlock(); if(silent && ecode == EKEEP) return false; throw Curia_error(ecode); } unlock(); return true; } bool Curia::out(const char* kbuf, int ksiz) throw(Curia_error){ if(!curia) throw Curia_error(); if(!lock()) throw Curia_error(); if(!crout(curia, kbuf, ksiz)){ int ecode = dpecode; unlock(); if(silent && ecode == ENOITEM) return false; throw Curia_error(ecode); } unlock(); return true; } char* Curia::get(const char* kbuf, int ksiz, int start, int max, int* sp) throw(Curia_error){ char* vbuf; if(!curia) throw Curia_error(); if(!lock()) throw Curia_error(); if(!(vbuf = crget(curia, kbuf, ksiz, start, max, sp))){ int ecode = dpecode; unlock(); if(silent && ecode == ENOITEM) return 0; throw Curia_error(ecode); } unlock(); return vbuf; } int Curia::getwb(const char *kbuf, int ksiz, int start, int max, char *vbuf) throw(Curia_error){ int vsiz; if(!curia) throw Curia_error(); if(!lock()) throw Curia_error(); if((vsiz = crgetwb(curia, kbuf, ksiz, start, max, vbuf)) == -1){ int ecode = dpecode; unlock(); if(silent && ecode == ENOITEM) return -1; throw Curia_error(ecode); } unlock(); return vsiz; } int Curia::vsiz(const char* kbuf, int ksiz) throw(Curia_error){ int vsiz; if(!curia) throw Curia_error(); if(!lock()) throw Curia_error(); if((vsiz = crvsiz(curia, kbuf, ksiz)) == -1){ int ecode = dpecode; unlock(); if(silent && ecode == ENOITEM) return -1; throw Curia_error(ecode); } unlock(); return vsiz; } void Curia::iterinit() throw(Curia_error){ if(!curia) throw Curia_error(); if(!lock()) throw Curia_error(); if(!criterinit(curia)){ int ecode = dpecode; unlock(); throw Curia_error(ecode); } unlock(); } char* Curia::iternext(int* sp) throw(Curia_error){ char* vbuf; if(!curia) throw Curia_error(); if(!lock()) throw Curia_error(); if(!(vbuf = criternext(curia, sp))){ int ecode = dpecode; unlock(); if(silent && ecode == ENOITEM) return 0; throw Curia_error(ecode); } unlock(); return vbuf; } void Curia::setalign(int align) throw(Curia_error){ if(!curia) throw Curia_error(); if(!lock()) throw Curia_error(); if(!crsetalign(curia, align)){ int ecode = dpecode; unlock(); throw Curia_error(ecode); } unlock(); } void Curia::setfbpsiz(int size) throw(Curia_error){ if(!curia) throw Curia_error(); if(!lock()) throw Curia_error(); if(!crsetfbpsiz(curia, size)){ int ecode = dpecode; unlock(); throw Curia_error(ecode); } unlock(); } void Curia::sync() throw(Curia_error){ if(!curia) throw Curia_error(); if(!lock()) throw Curia_error(); if(!crsync(curia)){ int ecode = dpecode; unlock(); throw Curia_error(ecode); } unlock(); } void Curia::optimize(int bnum) throw(Curia_error){ if(!curia) throw Curia_error(); if(!lock()) throw Curia_error(); if(!croptimize(curia, bnum)){ int ecode = dpecode; unlock(); throw Curia_error(ecode); } unlock(); } char* Curia::name() throw(Curia_error){ char* buf; if(!curia) throw Curia_error(); if(!lock()) throw Curia_error(); if(!(buf = crname(curia))){ int ecode = dpecode; unlock(); throw Curia_error(ecode); } unlock(); return buf; } int Curia::fsiz() throw(Curia_error){ int rv; if(!curia) throw Curia_error(); if(!lock()) throw Curia_error(); if((rv = crfsiz(curia)) == -1){ int ecode = dpecode; unlock(); throw Curia_error(ecode); } unlock(); return rv; } double Curia::fsizd() throw(Curia_error){ double rv; if(!curia) throw Curia_error(); if(!lock()) throw Curia_error(); if((rv = crfsizd(curia)) == -1){ int ecode = dpecode; unlock(); throw Curia_error(ecode); } unlock(); return rv; } int Curia::bnum() throw(Curia_error){ int rv; if(!curia) throw Curia_error(); if(!lock()) throw Curia_error(); if((rv = crbnum(curia)) == -1){ int ecode = dpecode; unlock(); throw Curia_error(ecode); } unlock(); return rv; } int Curia::busenum() throw(Curia_error){ int rv; if(!curia) throw Curia_error(); if(!lock()) throw Curia_error(); if((rv = crbusenum(curia)) == -1){ int ecode = dpecode; unlock(); throw Curia_error(ecode); } unlock(); return rv; } int Curia::rnum() throw(Curia_error){ int rv; if(!curia) throw Curia_error(); if(!lock()) throw Curia_error(); if((rv = crrnum(curia)) == -1){ int ecode = dpecode; unlock(); throw Curia_error(ecode); } unlock(); return rv; } bool Curia::writable() throw(Curia_error){ int rv; if(!curia) throw Curia_error(); if(!lock()) throw Curia_error(); rv = crwritable(curia); unlock(); return rv ? true : false; } bool Curia::fatalerror() throw(Curia_error){ int rv; if(!curia) throw Curia_error(); if(!lock()) throw Curia_error(); rv = crfatalerror(curia); unlock(); return rv ? true : false; } int Curia::inode() throw(Curia_error){ int rv; if(!curia) throw Curia_error(); if(!lock()) throw Curia_error(); rv = crinode(curia); unlock(); return rv; } time_t Curia::mtime() throw(Curia_error){ time_t rv; if(!curia) throw Curia_error(); if(!lock()) throw Curia_error(); rv = crmtime(curia); unlock(); return rv; } bool Curia::putlob(const char* kbuf, int ksiz, const char* vbuf, int vsiz, int dmode) throw(Curia_error){ if(!curia) throw Curia_error(); if(!lock()) throw Curia_error(); if(!crputlob(curia, kbuf, ksiz, vbuf, vsiz, dmode)){ int ecode = dpecode; unlock(); if(silent && ecode == EKEEP) return false; throw Curia_error(ecode); } unlock(); return true; } bool Curia::outlob(const char* kbuf, int ksiz) throw(Curia_error){ if(!curia) throw Curia_error(); if(!lock()) throw Curia_error(); if(!croutlob(curia, kbuf, ksiz)){ int ecode = dpecode; unlock(); if(silent && ecode == ENOITEM) return false; throw Curia_error(ecode); } unlock(); return true; } char* Curia::getlob(const char* kbuf, int ksiz, int start, int max, int* sp) throw(Curia_error){ char* vbuf; if(!curia) throw Curia_error(); if(!lock()) throw Curia_error(); if(!(vbuf = crgetlob(curia, kbuf, ksiz, start, max, sp))){ int ecode = dpecode; unlock(); if(silent && ecode == ENOITEM) return 0; throw Curia_error(ecode); } unlock(); return vbuf; } int Curia::getlobfd(const char *kbuf, int ksiz){ int fd; if(!curia) throw Curia_error(); if(!lock()) throw Curia_error(); if((fd = crgetlobfd(curia, kbuf, ksiz)) == -1){ int ecode = dpecode; unlock(); if(silent && ecode == ENOITEM) return -1; throw Curia_error(ecode); } unlock(); return fd; } int Curia::vsizlob(const char* kbuf, int ksiz) throw(Curia_error){ int vsiz; if(!curia) throw Curia_error(); if(!lock()) throw Curia_error(); if((vsiz = crvsizlob(curia, kbuf, ksiz)) == -1){ int ecode = dpecode; unlock(); if(silent && ecode == ENOITEM) return -1; throw Curia_error(ecode); } unlock(); return vsiz; } int Curia::rnumlob() throw(Curia_error){ int rv; if(!curia) throw Curia_error(); if(!lock()) throw Curia_error(); rv = crrnumlob(curia); unlock(); return rv; } void Curia::storerec(const Datum& key, const Datum& val, bool replace) throw(Curia_error){ if(!put(key.ptr(), key.size(), val.ptr(), val.size(), replace ? CR_DOVER : CR_DKEEP)) throw Curia_error(EKEEP); } void Curia::deleterec(const Datum& key) throw(Curia_error){ if(!out(key.ptr(), key.size())) throw Curia_error(ENOITEM); } Datum Curia::fetchrec(const Datum& key) throw(Curia_error){ char* vbuf; int vsiz; vbuf = get(key.ptr(), key.size(), 0, -1, &vsiz); if(!vbuf) throw Curia_error(ENOITEM); return Datum(vbuf, vsiz, true); } Datum Curia::firstkey() throw(Curia_error){ iterinit(); return nextkey(); } Datum Curia::nextkey() throw(Curia_error){ char* kbuf; int ksiz; kbuf = iternext(&ksiz); if(!kbuf) throw Curia_error(ENOITEM); return Datum(kbuf, ksiz, true); } bool Curia::error() throw(Curia_error){ return fatalerror(); } Curia::Curia(const Curia& curia) throw(Curia_error){ throw Curia_error(); } Curia& Curia::operator =(const Curia& curia) throw(Curia_error){ throw Curia_error(); } bool Curia::lock(){ if(dpisreentrant){ if(pthread_mutex_lock(&mymutex) != 0) return false; return true; } if(pthread_mutex_lock(&ourmutex) != 0) return false; return true; } void Curia::unlock(){ if(dpisreentrant){ pthread_mutex_unlock(&mymutex); } else { pthread_mutex_unlock(&ourmutex); } } /* END OF FILE */ qdbm-1.8.78/plus/xspex.html0000644000175000017500000003430011426311503014560 0ustar mikiomikio Specifications of QDBM for C++

Specifications of QDBM for C++

Copyright (C) 2000-2006 Mikio Hirabayashi
Last Update: Thu, 26 Oct 2006 15:00:20 +0900

Table of Contents

  1. Overview
  2. Installation
  3. Examples
  4. Bugs

Overview

QDBM provides API for C++. This encapsulates the basic API, the extended API and the advanced API of QDBM, and make them thread-safe.

The basic API for C++ realizes a hash database with a file. Constructors of the class `Depot' open a database file. The member function `close' is used in order to close the database. If the instance is destroyed without closing the database explicitly, the destructor closes the database. The member function `put' is used in order to store a record. The member function `out' is used in order to delete a record. The member function `get' is used in order to retrieve a record. Besides, most operations like ones of the basic API for C are available. Each member functions throws an instance of the class `Depot_error' if an error occurs.

The extended API for C++ realizes a hash database with a directory and multiple files. Constructors of the class `Curia' open a database directory. The member function `close' is used in order to close the database. If the instance is destroyed without closing the database explicitly, the destructor closes the database. The member function `put' is used in order to store a record. The member function `out' is used in order to delete a record. The member function `get' is used in order to retrieve a record. Operations for managing large objects are also provided. Besides, most operations like ones of the extended API for C are available. Each member functions throws an instance of the class `Curia_error' if an error occurs.

The advanced API for C++ realizes a B+ tree database with a file. Constructors of the class `Villa' open a database file. The member function `close' is used in order to close the database. If the instance is destroyed without closing the database explicitly, the destructor closes the database. The member function `put' is used in order to store a record. The member function `out' is used in order to delete a record. The member function `get' is used in order to retrieve a record. Besides, most operations like ones of the advanced API for C are available. Each member functions throws an instance of the class `Villa_error' if an error occurs.

`Depot', `Curia', and `Villa' are derived classes of the class `ADBM'. This class is an interface for abstraction of database managers compatible with DBM of UNIX standard. This class does only declare pure virtual functions. Each member functions throws an instance of the class `DBM_error'. In this framework, a key and a value of each record are expressed by the class `Datum'. An instance of `Datum' has the pointer to the region of data and its size. When you choose the one of four APIs, `Depot' is suggested if performance is weighted, `Curia' is suggested if scalability is weighted, `Villa' is suggested if ordering access is required, `ADBM' is suggested if elegance and maintenance are weighted. Besides, a database file is not compatible with each API.

You should include the following header files in source files of applications: `xdepot.h' for `Depot', `xcuria.h' for `Curia', `xvilla.h' for `Villa', and `xadbm.h' for `ADBM'. Besides, each class is packaged in the name space `qdbm'.

While APIs for C are thread-safe unless plural threads do not share a database handle, APIs for C++ are thread-safe even if plural threads share a handle. This API is implemented depending on the POSIX thread package. If you use another thread package, you should write your own C++ wrapper.

When `put' overwriting an existing record is cancelled or `get' retrieving a missing record, failure of the operation is noticed by exception. If you dislike such behavior, set the `silent' flag to be true. Then, failure of the operation is noticed by the return value.

For more information about the APIs, read documents in the sub directory `xapidoc' and each header file.


Installation

Preparation

Make sure that GCC 3.3 or later version is installed. And make sure that QDBM is installed under `/usr/local'.

Change the current working directory to the sub directory named `plus'.

cd plus

Usual Steps

Run the configuration script.

./configure

Build programs.

make

Perform self-diagnostic test.

make check

Install programs. This operation must be carried out by the root user.

make install

When a series of work finishes, header files, `xdepot.h', `xcuria.h', `xvilla.h', and `xadbm.h' will be installed in `/usr/local/include', a library `libxqdbm.so' and so on will be installed in `/usr/local/lib', executable commands `xdptest', `xcrtest', and `xvltest' will be installed in `/usr/local/bin'.

To uninstall them, execute the following command after `./configure'. This operation must be carried out by the root user.

make uninstall

For Windows

On Windows (Cygwin), you should follow the procedures below for installation.

Run the configuration script.

./configure

Build programs.

make win

Perform self-diagnostic test.

make check-win

Install programs. As well, perform `make uninstall-win' to uninstall them.

make install-win

On Windows, an import library `libxqdbm.dll.a' is created, and a dynamic linking library `jqdbm.dll' is created. `xqdbm.dll' is installed into `/usr/local/bin'.

Build of the C++ API using MinGW is not supported.

For Mac OS X

On Mac OS X (Darwin), you should follow the procedures below for installation.

Run the configuration script.

./configure

Build programs.

make mac

Perform self-diagnostic test.

make check-mac

Install programs. As well, perform `make uninstall-mac' to uninstall them.

make install-mac

On Mac OS X, `libxqdbm.dylib' and so on are created instead of `libxqdbm.so' and so on.

For HP-UX

On HP-UX, you should follow the procedures below for installation.

Run the configuration script.

./configure

Build programs.

make hpux

Perform self-diagnostic test.

make check-hpux

Install programs. As well, perform `make uninstall-hpux' to uninstall them.

make install-hpux

On HP-UX, `libxqdbm.sl' is created instead of `libxqdbm.so' and so on.


Examples

The following example stores and retrieves a phone number, using the name as the key.

#include <xdepot.h>
#include <cstdlib>
#include <iostream>

using namespace std;
using namespace qdbm;

const char* NAME = "mikio";
const char* NUMBER = "000-1234-5678";
const char* DBNAME = "book";

int main(int argc, char** argv){
  try {

    // open the database
    Depot depot(DBNAME, Depot::OWRITER | Depot::OCREAT);

    // store the record
    depot.put(NAME, -1, NUMBER, -1);

    // retrieve the record
    char* val = depot.get(NAME, -1);
    cout << "Name: " << NAME << endl;
    cout << "Number: " << val << endl;
    free(val);

    // close the database
    depot.close();

  } catch(Depot_error& e){
    cerr << e << endl;
    return 1;
  }
  return 0;
}

The following example is a transcription of the one above, using the class `ADBM'.

#include <xadbm.h>
#include <xdepot.h>
#include <iostream>

using namespace std;
using namespace qdbm;

const char* NAME = "mikio";
const char* NUMBER = "000-1234-5678";
const char* DBNAME = "book";

int main(int argc, char** argv){
  try {

    // open the database
    Depot depot(DBNAME, Depot::OWRITER | Depot::OCREAT);
    ADBM& dbm = depot;

    // prepare the record
    Datum key(NAME);
    Datum val(NUMBER);

    // store the record
    dbm.storerec(key, val);

    // retrieve the record
    const Datum& res = dbm.fetchrec(key);
    cout << "Name: " << NAME << endl;
    cout << "Number: " << res << endl;

    // close the database
    dbm.close();

  } catch(DBM_error& e){
    cerr << e << endl;
    return 1;
  }
  return 0;
}

The following example performs forward matching search for strings, using the class `Villa'.

#include <xvilla.h>
#include <cstdlib>
#include <cstring>
#include <iostream>

using namespace std;
using namespace qdbm;

const char* DBNAME = "words";
const char* PREFIX = "apple";

int main(int argc, char** argv){
  try {

    // open the database
    Villa villa(DBNAME, Villa::OWRITER | Villa::OCREAT);

    // store records
    villa.put("applet", -1, "little application", -1, Villa::DDUP);
    villa.put("aurora", -1, "polar wonderwork", -1, Villa::DDUP);
    villa.put("apple", -1, "delicious fruit", -1, Villa::DDUP);
    villa.put("amigo", -1, "good friend", -1, Villa::DDUP);
    villa.put("apple", -1, "big city", -1, Villa::DDUP);

    try {

      // set the cursor at the top of candidates
      villa.curjump(PREFIX, -1);

      // scan with the cursor
      for(;;){
        char* key = villa.curkey();
        if(strstr(key, PREFIX) != key){
          free(key);
          break;
        }
        char* val = villa.curval();
        cout << key << ": " << val << endl;
        free(key);
        free(val);
        villa.curnext();
      }

    } catch(Villa_error& e){
      if(e.code() != Villa::ENOITEM) throw e;
    }

    // close the database
    villa.close();

  } catch(Villa_error& e){
    cerr << e << endl;
    return 1;
  }
  return 0;
}

For building a program using C++ API of QDBM, the program should be linked with the libraries: `xqdbm' and `qdbm'. For example, the following command is executed to build `sample' from `sample.cc'.

g++ -I/usr/local/include -o sample sample.cc -L/usr/local/lib -lxqdbm -lqdbm

Bugs

QDBM has restrictions that two or more handles of the same database file should not be used by a process at the same time. So, when a database is used by two or more threads, open the database in the main thread and pass the handle to each thread.

Because QDBM does not provide mechanism that serialize generic objects and store them into a database, if you want it, you should extend the class `ADBM'. Besides, if the comparing function of `Villa' compares deserialized objects, the database can be used as an object-oriented database.


qdbm-1.8.78/plus/xcuria.h0000644000175000017500000006614310505721655014213 0ustar mikiomikio/************************************************************************************************* * C++ API of Curia, the extended API of QDBM * Copyright (C) 2000-2006 Mikio Hirabayashi * This file is part of QDBM, Quick Database Manager. * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU * Lesser General Public License as published by the Free Software Foundation; either version * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * You should have received a copy of the GNU Lesser General Public License along with QDBM; if * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. *************************************************************************************************/ #ifndef _XCURIA_H /* duplication check */ #define _XCURIA_H #include #include extern "C" { #include #include #include #include } /** * Error container for Curia. */ class qdbm::Curia_error : public virtual DBM_error { //---------------------------------------------------------------- // public member functions //---------------------------------------------------------------- public: /** * Create an instance. */ Curia_error() throw(); /** * Create an instance. * @param ecode the error code. */ Curia_error(int ecode) throw(); /** * Copy constructor. * @param ce a source instance. */ Curia_error(const Curia_error& ce) throw(); /** * Release resources of the instance. */ virtual ~Curia_error() throw(); /** * Assignment operator. * @param ce a source instance. * @return reference to itself. */ Curia_error& operator =(const Curia_error& ce) throw(); /** * Assignment operator. * @param ecode the error code. * @return reference to itself. */ Curia_error& operator =(int ecode) throw(); /** * Equality operator. * @param ce a comparing instance. * @return true if both equal, else, false. */ virtual bool operator ==(const Curia_error& ce) const throw(); /** * Inequality operator. * @param ce a comparing instance. * @return true if both do not equal, else, false. */ virtual bool operator !=(const Curia_error& ce) const throw(); /** * Equality operator. * @param ecode a comparing error code. * @return true if both equal, else, false. */ virtual bool operator ==(int ecode) const throw(); /** * Inequality operator. * @param ecode a comparing error code. * @return true if both do not equal, else, false. */ virtual bool operator !=(int ecode) const throw(); /** * Cast operator into pointer to char. * @return the pointer to the string. */ virtual operator const char*() const throw(); /** * Get the error code. * @return the error code. */ virtual int code() const throw(); /** * Get the error message. * @return the pointer to the string. */ virtual const char* message() const throw(); //---------------------------------------------------------------- // private member variables //---------------------------------------------------------------- private: /** The error code. */ int ecode; }; /** * C++ API of Curia, the extended API of QDBM */ class qdbm::Curia : public virtual ADBM { //---------------------------------------------------------------- // public static member constants //---------------------------------------------------------------- public: static const int ENOERR; ///< error code: no error static const int EFATAL; ///< error code: with fatal error static const int EMODE; ///< error code: invalid mode static const int EBROKEN; ///< error code: broken database file static const int EKEEP; ///< error code: existing record static const int ENOITEM; ///< error code: no item found static const int EALLOC; ///< error code: memory allocation error static const int EMAP; ///< error code: memory mapping error static const int EOPEN; ///< error code: open error static const int ECLOSE; ///< error code: close error static const int ETRUNC; ///< error code: trunc error static const int ESYNC; ///< error code: sync error static const int ESTAT; ///< error code: stat error static const int ESEEK; ///< error code: seek error static const int EREAD; ///< error code: read error static const int EWRITE; ///< error code: write error static const int ELOCK; ///< error code: lock error static const int EUNLINK; ///< error code: unlink error static const int EMKDIR; ///< error code: mkdir error static const int ERMDIR; ///< error code: rmdir error static const int EMISC; ///< error code: miscellaneous error static const int OREADER; ///< open mode: open as a reader static const int OWRITER; ///< open mode: open as a writer static const int OCREAT; ///< open mode: writer creating static const int OTRUNC; ///< open mode: writer truncating static const int ONOLCK; ///< open mode: open without locking static const int OLCKNB; ///< open mode: lock without blocking static const int OSPARSE; ///< open mode: create as sparse files static const int DOVER; ///< write mode: overwrite the existing value static const int DKEEP; ///< write mode: keep the existing value static const int DCAT; ///< write mode: concatenate values //---------------------------------------------------------------- // public static member functions //---------------------------------------------------------------- public: /** * Get the version information. * @return the string of the version information. */ static const char* version() throw(); /** * Remove a database directory. * @param name the name of a database directory. * @throw Curia_error if an error occurs. */ static void remove(const char* name) throw(Curia_error); /** * Retrieve a record directly from a database directory. * @param name the name of a database directory. * @param kbuf the pointer to the region of a key. * @param ksiz the size of the region of the key. If it is negative, the size is assigned * with `std::strlen(kbuf)'. * @param sp the pointer to a variable to which the size of the region of the return value * is assigned. If it is 0, it is not used. * @return the pointer to the region of the value of the corresponding record. * @throw Curia_error if an error occurs or no record corresponds. * @note Because an additional zero code is appended at the end of the region of the return * value, the return value can be treated as a character string. Because the region of the * return value is allocated with the `std::malloc' call, it should be released with the * `std::free' call if it is no longer in use. Although this method can be used even while * the database directory is locked by another process, it is not assured that recent updated * is reflected. */ static char* snaffle(const char* name, const char* kbuf, int ksiz, int* sp) throw(Curia_error); //---------------------------------------------------------------- // public member functions //---------------------------------------------------------------- public: /** * Get the database handle. * @param name the name of a database directory. * @param omode the connection mode: `Curia::OWRITER' as a writer, `Curia::OREADER' as * a reader. If the mode is `Curia::OWRITER', the following may be added by bitwise or: * `Curia::OCREAT', which means it creates a new database if not exist, `Curia::OTRUNC', * which means it creates a new database regardless if one exists. Both of `Curia::OREADER' * and `Curia::OWRITER' can be added to by bitwise or: `Curia::ONOLCK', which means it opens a * database directory without file locking, or `Curia::OLCKNB', which means locking is * performed without blocking. `Curia::OCREAT' can be added to by bitwise or: `Curia::OSPARSE', * which means it creates database files as sparse files. * @param bnum the number of elements of each bucket array. If it is not more than 0, * the default value is specified. The size of each bucket array is determined on creating, * and can not be changed except for by optimization of the database. Suggested size of each * bucket array is about from 0.5 to 4 times of the number of all records to store. * @param dnum the number of division of the database. If it is not more than 0, the default * value is specified. The number of division can not be changed from the initial value. The * max number of division is 512. * @note While connecting as a writer, an exclusive lock is invoked to the database directory. * While connecting as a reader, a shared lock is invoked to the database directory. * The thread blocks until the lock is achieved. If `Curia::ONOLCK' is used, the application * is responsible for exclusion control. */ Curia(const char* name, int omode = Curia::OREADER, int bnum = -1, int dnum = -1) throw(Curia_error); /** * Release the resources. * @note If the database handle is not closed yet, it is closed. */ virtual ~Curia() throw(); /** * Close the database handle. * @throw Curia_error if an error occurs. * @note Updating a database is assured to be written when the handle is closed. If a writer * opens a database but does not close it appropriately, the database will be broken. */ virtual void close() throw(Curia_error); /** * Store a record. * @param kbuf the pointer to the region of a key. * @param ksiz the size of the region of the key. If it is negative, the size is assigned * with `std::strlen(kbuf)'. * @param vbuf the pointer to the region of a value. * @param vsiz the size of the region of the value. If it is negative, the size is assigned * with `std::strlen(vbuf)'. * @param dmode behavior when the key overlaps, by the following values: `Curia::DOVER', * which means the specified value overwrites the existing one, `Curia::DKEEP', which means the * existing value is kept, `Curia::DCAT', which means the specified value is concatenated at * the end of the existing value. * @return always true. However, if the silent flag is true and replace is cancelled, false is * returned instead of exception. * @throw Curia_error if an error occurs or replace is cancelled. */ virtual bool put(const char* kbuf, int ksiz, const char* vbuf, int vsiz, int dmode = Curia::DOVER) throw(Curia_error); /** * Delete a record. * @param kbuf the pointer to the region of a key. * @param ksiz the size of the region of the key. If it is negative, the size is assigned * with `std::strlen(kbuf)'. * @return always true. However, if the silent flag is true and no record corresponds, false * is returned instead of exception. * @throw Curia_error if an error occurs or no record corresponds. */ virtual bool out(const char* kbuf, int ksiz) throw(Curia_error); /** * Retrieve a record. * @param kbuf the pointer to the region of a key. * @param ksiz the size of the region of the key. If it is negative, the size is assigned * with `std::strlen(kbuf)'. * @param start the offset address of the beginning of the region of the value to be read. * @param max the max size to read with. If it is negative, the size is unlimited. * @param sp the pointer to a variable to which the size of the region of the return value * is assigned. If it is 0, it is not used. * @return the pointer to the region of the value of the corresponding record. If the silent * flag is true and no record corresponds, 0 is returned instead of exception. * @throw Curia_error if an error occurs, no record corresponds, or the size of the value * of the corresponding record is less than `start'. * @note Because an additional zero code is appended at the end of the region of the return * value, the return value can be treated as a character string. Because the region of the * return value is allocated with the `std::malloc' call, it should be released with the * `std::free' call if it is no longer in use. */ virtual char* get(const char* kbuf, int ksiz, int start = 0, int max = -1, int* sp = 0) throw(Curia_error); /** * Retrieve a record and write the value into a buffer. * @param kbuf the pointer to the region of a key. * @param ksiz the size of the region of the key. If it is negative, the size is assigned * with `std::strlen(kbuf)'. * @param start the offset address of the beginning of the region of the value to be read. * @param max the max size to be read. It shuld be equal to or less than the size of the * writing buffer. * @param vbuf the pointer to a buffer into which the value of the corresponding record is * written. * @return the return value is the size of the written data. If the silent flag is true and * no record corresponds, -1 is returned instead of exception. * @throw Curia_error if an error occurs, no record corresponds, or the size of the value * of the corresponding record is less than `start'. * @note No additional zero code is appended at the end of the region of the writing buffer. */ virtual int getwb(const char *kbuf, int ksiz, int start, int max, char *vbuf) throw(Curia_error); /** * Get the size of the value of a record. * @param kbuf the pointer to the region of a key. * @param ksiz the size of the region of the key. If it is negative, the size is assigned * with `std::strlen(kbuf)'. * @return the size of the value of the corresponding record. If the silent flag is true and * no record corresponds, -1 is returned instead of exception. * @throw Curia_error if an error occurs or no record corresponds. * @note Because this function does not read the entity of a record, it is faster than `get'. */ virtual int vsiz(const char* kbuf, int ksiz) throw(Curia_error); /** * Initialize the iterator of the database handle. * @throw Curia_error if an error occurs. * @note The iterator is used in order to access the key of every record stored in a database. */ virtual void iterinit() throw(Curia_error); /** * Get the next key of the iterator. * @param sp the pointer to a variable to which the size of the region of the return value is * assigned. If it is 0, it is not used. * @return the pointer to the region of the next key. If the silent flag is true and no record * corresponds, 0 is returned instead of exception. * @throw Curia_error if an error occurs or no record is to be get out of the iterator. * @note Because an additional zero code is appended at the end of the region of the return * value, the return value can be treated as a character string. Because the region of the * return value is allocated with the `std::malloc' call, it should be released with the * `std::free' call if it is no longer in use. It is possible to access every record by * iteration of calling this function. However, it is not assured if updating the database * is occurred while the iteration. Besides, the order of this traversal access method is * arbitrary, so it is not assured that the order of storing matches the one of the traversal * access. */ virtual char* iternext(int* sp = 0) throw(Curia_error); /** * Set alignment of the database handle. * @param align the basic size of alignment. * @throw Curia_error if an error occurs. * @note If alignment is set to a database, the efficiency of overwriting values is improved. * The size of alignment is suggested to be average size of the values of the records to be * stored. If alignment is positive, padding whose size is multiple number of the alignment * is placed. If alignment is negative, as `vsiz' is the size of a value, the size of padding * is calculated with `(vsiz / pow(2, abs(align) - 1))'. Because alignment setting is not * saved in a database, you should specify alignment every opening a database. */ virtual void setalign(int align) throw(Curia_error); /** * Set the size of the free block pool. * @param size the size of the free block pool of a database. * @throw Curia_error if an error occurs. * @note The default size of the free block pool is 16. If the size is greater, the space * efficiency of overwriting values is improved with the time efficiency sacrificed. */ virtual void setfbpsiz(int size) throw(Curia_error); /** * Synchronize updating contents with the files and the devices. * @note Curia_error if an error occurs. * This function is useful when another process uses the connected database directory. */ virtual void sync() throw(Curia_error); /** * Optimize the database. * @param bnum the number of the elements of each bucket array. If it is not more than 0, * the default value is specified. * @throw Curia_error if an error occurs. * @note In an alternating succession of deleting and storing with overwrite or concatenate, * dispensable regions accumulate. This function is useful to do away with them. */ virtual void optimize(int bnum = -1) throw(Curia_error); /** * Get the name of the database. * @return the pointer to the region of the name of the database. * @throw Curia_error if an error occurs. * @note Because the region of the return value is allocated with the `std::malloc' call, * it should be released with the `std::free' call if it is no longer in use. */ virtual char* name() throw(Curia_error); /** * Get the total size of database files. * @return the total size of the database files. * @throw Curia_error if an error occurs. * @note If the total size is more than 2GB, the return value overflows. */ virtual int fsiz() throw(Curia_error); /** * Get the total size of database files as double-precision floating-point number. * @return the total size of the database files. * @throw Curia_error if an error occurs. */ virtual double fsizd() throw(Curia_error); /** * Get the total number of the elements of each bucket array. * @return the total number of the elements of each bucket array. * @throw Curia_error if an error occurs. */ virtual int bnum() throw(Curia_error); /** * Get the total number of the used elements of each bucket array. * @return the total number of the used elements of each bucket array. * @throw Curia_error if an error occurs. * @note This function is inefficient because it accesses all elements of each bucket array. */ virtual int busenum() throw(Curia_error); /** * Get the number of the records stored in the database. * @return the number of the records stored in the database. * @throw Curia_error if an error occurs. */ virtual int rnum() throw(Curia_error); /** * Check whether the database handle is a writer or not. * @return true if the handle is a writer, false if not. * @throw Curia_error if an error occurs. */ virtual bool writable() throw(Curia_error); /** * Check whether the database has a fatal error or not. * @return true if the database has a fatal error, false if not. * @throw Curia_error if an error occurs. */ virtual bool fatalerror() throw(Curia_error); /** * Get the inode number of the database directory. * @return the inode number of the database directory. * @throw Curia_error if an error occurs. */ virtual int inode() throw(Curia_error); /** * Get the last modified time of the database. * @return the last modified time the database. * @throw Curia_error if an error occurs. */ virtual time_t mtime() throw(Curia_error); /** * Store a large object. * @param kbuf the pointer to the region of a key. * @param ksiz the size of the region of the key. If it is negative, the size is assigned * with `std::strlen(kbuf)'. * @param vbuf the pointer to the region of a value. * @param vsiz the size of the region of the value. If it is negative, the size is assigned * with `std::strlen(vbuf)'. * @param dmode behavior when the key overlaps, by the following values: `Curia::DOVER', * which means the specified value overwrites the existing one, `Curia::DKEEP', which means the * existing value is kept, `Curia::DCAT', which means the specified value is concatenated at * the end of the existing value. * @return always true. However, if the silent flag is true and replace is cancelled, false is * returned instead of exception. * @throw Curia_error if an error occurs or replace is cancelled. */ virtual bool putlob(const char* kbuf, int ksiz, const char* vbuf, int vsiz, int dmode = Curia::DOVER) throw(Curia_error); /** * Delete a large object. * @param kbuf the pointer to the region of a key. * @param ksiz the size of the region of the key. If it is negative, the size is assigned * with `std::strlen(kbuf)'. * @return always true. However, if the silent flag is true and no record corresponds, false * is returned instead of exception. * @throw Curia_error if an error occurs or no large object corresponds. */ virtual bool outlob(const char* kbuf, int ksiz) throw(Curia_error); /** * Retrieve a large object. * @param kbuf the pointer to the region of a key. * @param ksiz the size of the region of the key. If it is negative, the size is assigned * with `std::strlen(kbuf)'. * @param start the offset address of the beginning of the region of the value to be read. * @param max the max size to be read. If it is negative, the size to read is unlimited. * @param sp the pointer to a variable to which the size of the region of the return value * is assigned. If it is 0, it is not used. * @return the pointer to the region of the value of the corresponding large object. If the * silent flag is true and no record corresponds, 0 is returned instead of exception. * @throw Curia_error if an error occurs, no record corresponds, or the size of the value * of the corresponding record is less than `start'. * @note Because an additional zero code is appended at the end of the region of the return * value, the return value can be treated as a character string. Because the region of the * return value is allocated with the `std::malloc' call, it should be released with the * `std::free' call if it is no longer in use. */ virtual char* getlob(const char* kbuf, int ksiz, int start = 0, int max = -1, int* sp = 0) throw(Curia_error); /** * Get the file descriptor of a large object. * @param kbuf the pointer to the region of a key. * @param ksiz the size of the region of the key. If it is negative, the size is assigned * with `std::strlen(kbuf)'. * @return the file descriptor of the corresponding large object. If the silent flag is true * and no record corresponds, -1 is returned instead of exception. * @throw Curia_error if an error occurs or no record corresponds. * @note The returned file descriptor is opened with the `open' call. If the database handle * was opened as a writer, the descriptor is writable (O_RDWR), else, it is not writable * (O_RDONLY). The descriptor should be closed with the `close' call if it is no longer in use. */ virtual int getlobfd(const char *kbuf, int ksiz); /** * Get the size of the value of a large object. * @param kbuf the pointer to the region of a key. * @param ksiz the size of the region of the key. If it is negative, the size is assigned * with `std::strlen(kbuf)'. * @return the size of the value of the corresponding large object. If the silent flag is true * and no record corresponds, -1 is returned instead of exception. * @throw Curia_error if an error occurs or no large object corresponds. * @note Because this function does not read the entity of a large object, it is faster than * `getlob'. */ virtual int vsizlob(const char* kbuf, int ksiz) throw(Curia_error); /** * Get the number of the large objects stored in the database. * @return the number of the large objects stored in the database. * @throw Curia_error if an error occurs. */ virtual int rnumlob() throw(Curia_error); /** * Store a record. * @param key reference to a key object. * @param val reference to a value object. * @param replace whether the existing value is to be overwritten or not. * @throw Curia_error if an error occurs or replace is cancelled. */ virtual void storerec(const Datum& key, const Datum& val, bool replace = true) throw(Curia_error); /** * Delete a record. * @param key reference to a key object. * @throw Curia_error if an error occurs or no record corresponds. */ virtual void deleterec(const Datum& key) throw(Curia_error); /** * Fetch a record. * @param key reference to a key object. * @return a temporary instance of the value of the corresponding record. * @throw Curia_error if an error occurs or no record corresponds. */ virtual Datum fetchrec(const Datum& key) throw(Curia_error); /** * Get the first key. * @return a temporary instance of the key of the first record. * @throw Curia_error if an error occurs or no record corresponds. */ virtual Datum firstkey() throw(Curia_error); /** * Get the next key. * @return a temporary instance of the key of the next record. * @throw Curia_error if an error occurs or no record corresponds. */ virtual Datum nextkey() throw(Curia_error); /** * Check whether a fatal error occured or not. * @return true if the database has a fatal error, false if not. * @throw Curia_error if an error occurs. */ virtual bool error() throw(Curia_error); //---------------------------------------------------------------- // public member variables //---------------------------------------------------------------- public: bool silent; ///< whether to repress frequent exceptions //---------------------------------------------------------------- // private member variables //---------------------------------------------------------------- private: CURIA *curia; ///< internal database handle pthread_mutex_t mymutex; ///< internal mutex //---------------------------------------------------------------- // private member functions //---------------------------------------------------------------- private: /** copy constructor: This should not be used. */ Curia(const Curia& curia) throw(Curia_error); /** assignment operator: This should not be used. */ Curia& operator =(const Curia& curia) throw(Curia_error); /** lock the database. */ bool lock(); /** unlock the database. */ void unlock(); }; #endif /* duplication check */ /* END OF FILE */ qdbm-1.8.78/plus/xspex-ja.html0000644000175000017500000004067311426311515015165 0ustar mikiomikio Specifications of QDBM for C++ (Japanese)

QDBM付属C++用API仕様書

Copyright (C) 2000-2006 Mikio Hirabayashi
Last Update: Thu, 26 Oct 2006 15:00:20 +0900

目次

  1. 概è¦
  2. インストール
  3. サンプルコード
  4. ãƒã‚°

概è¦

QDBMã«ã¯C++言語用ã®APIãŒã‚る。QDBMã®åŸºæœ¬APIã¨æ‹¡å¼µAPIã¨ä¸Šç´šAPIã®é–¢æ•°ç¾¤ã‚’C++ã®ã‚¯ãƒ©ã‚¹æ©Ÿæ§‹ã‚’用ã„ã¦ã‚«ãƒ—セル化ã—ã€ã‹ã¤ã‚¹ãƒ¬ãƒƒãƒ‰ã‚»ãƒ¼ãƒ•ã«ã—ãŸã‚‚ã®ã§ã‚る。

基本APIã¯ãƒ•ァイルを用ã„ã¦ãƒãƒƒã‚·ãƒ¥ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’実ç¾ã™ã‚‹ã€‚クラス `Depot' ã®ã‚³ãƒ³ã‚¹ãƒˆãƒ©ã‚¯ã‚¿ã«ã‚ˆã£ã¦ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルãŒé–‹ã‹ã‚Œã‚‹ã€‚データベースを閉ã˜ã‚‹ã«ã¯ãƒ¡ãƒ³ãƒé–¢æ•° `close' を呼ã¶ã€‚明示的ã«ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’é–‰ã˜ãªã„ã§ã‚¤ãƒ³ã‚¹ã‚¿ãƒ³ã‚¹ãŒç ´æ£„ã•れる場åˆã¯ã€ãƒ‡ã‚¹ãƒˆãƒ©ã‚¯ã‚¿ã«ã‚ˆã£ã¦ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãŒé–‰ã˜ã‚‰ã‚Œã‚‹ã€‚メンãƒé–¢æ•° `put' ã¯ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’追加ã™ã‚‹ãŸã‚ã«ç”¨ã„る。メンãƒé–¢æ•° `out' ã¯ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’削除ã™ã‚‹ãŸã‚ã«ç”¨ã„る。メンãƒé–¢æ•° `get' ã¯ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’検索ã™ã‚‹ãŸã‚ã«ç”¨ã„る。ãã®ä»–ã«ã‚‚ã€C言語ã®åŸºæœ¬APIã¨ã»ã¼åŒã˜æ“作を利用ã™ã‚‹ã“ã¨ãŒã§ãる。å„メンãƒé–¢æ•°ã¯ã‚¨ãƒ©ãƒ¼æ™‚ã«ã‚¯ãƒ©ã‚¹ `Depot_error' ã®ã‚¤ãƒ³ã‚¹ã‚¿ãƒ³ã‚¹ã‚’投ã’る。

æ‹¡å¼µAPIã¯ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã¨è¤‡æ•°ã®ãƒ•ァイルを用ã„ã¦ãƒãƒƒã‚·ãƒ¥ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’実ç¾ã™ã‚‹ã€‚クラス `Curia' ã®ã‚³ãƒ³ã‚¹ãƒˆãƒ©ã‚¯ã‚¿ã«ã‚ˆã£ã¦ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªãŒé–‹ã‹ã‚Œã‚‹ã€‚データベースを閉ã˜ã‚‹ã«ã¯ãƒ¡ãƒ³ãƒé–¢æ•° `close' を呼ã¶ã€‚明示的ã«ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’é–‰ã˜ãªã„ã§ã‚¤ãƒ³ã‚¹ã‚¿ãƒ³ã‚¹ãŒç ´æ£„ã•れる場åˆã¯ã€ãƒ‡ã‚¹ãƒˆãƒ©ã‚¯ã‚¿ã«ã‚ˆã£ã¦ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãŒé–‰ã˜ã‚‰ã‚Œã‚‹ã€‚メンãƒé–¢æ•° `put' ã¯ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’追加ã™ã‚‹ãŸã‚ã«ç”¨ã„る。メンãƒé–¢æ•° `out' ã¯ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’削除ã™ã‚‹ãŸã‚ã«ç”¨ã„る。メンãƒé–¢æ•° `get' ã¯ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’検索ã™ã‚‹ãŸã‚ã«ç”¨ã„る。ラージオブジェクトを扱ã†ã“ã¨ã‚‚ã§ãる。ãã®ä»–ã«ã‚‚ã€Cè¨€èªžã®æ‹¡å¼µAPIã¨ã»ã¼åŒã˜æ“作を利用ã™ã‚‹ã“ã¨ãŒã§ãる。å„メンãƒé–¢æ•°ã¯ã‚¨ãƒ©ãƒ¼æ™‚ã«ã‚¯ãƒ©ã‚¹ `Curia_error' ã®ã‚¤ãƒ³ã‚¹ã‚¿ãƒ³ã‚¹ã‚’投ã’る。

上級APIã¯ãƒ•ァイルを用ã„ã¦B+木データベースを実ç¾ã™ã‚‹ã€‚クラス `Villa' ã®ã‚³ãƒ³ã‚¹ãƒˆãƒ©ã‚¯ã‚¿ã«ã‚ˆã£ã¦ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルãŒé–‹ã‹ã‚Œã‚‹ã€‚データベースを閉ã˜ã‚‹ã«ã¯ãƒ¡ãƒ³ãƒé–¢æ•° `close' を呼ã¶ã€‚明示的ã«ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’é–‰ã˜ãªã„ã§ã‚¤ãƒ³ã‚¹ã‚¿ãƒ³ã‚¹ãŒç ´æ£„ã•れる場åˆã¯ã€ãƒ‡ã‚¹ãƒˆãƒ©ã‚¯ã‚¿ã«ã‚ˆã£ã¦ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãŒé–‰ã˜ã‚‰ã‚Œã‚‹ã€‚メンãƒé–¢æ•° `put' ã¯ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’追加ã™ã‚‹ãŸã‚ã«ç”¨ã„る。メンãƒé–¢æ•° `out' ã¯ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’削除ã™ã‚‹ãŸã‚ã«ç”¨ã„る。メンãƒé–¢æ•° `get' ã¯ãƒ¬ã‚³ãƒ¼ãƒ‰ã‚’検索ã™ã‚‹ãŸã‚ã«ç”¨ã„る。ãã®ä»–ã«ã‚‚ã€C言語ã®ä¸Šç´šAPIã¨ã»ã¼åŒã˜æ“作を利用ã™ã‚‹ã“ã¨ãŒã§ãる。å„メンãƒé–¢æ•°ã¯ã‚¨ãƒ©ãƒ¼æ™‚ã«ã‚¯ãƒ©ã‚¹ `Villa_error' ã®ã‚¤ãƒ³ã‚¹ã‚¿ãƒ³ã‚¹ã‚’投ã’る。

`Depot' 㨠`Curia' 㨠`Villa' ã¯ã‚¯ãƒ©ã‚¹ `ADBM' ã®æ´¾ç”Ÿã‚¯ãƒ©ã‚¹ã§ã‚る。ã“ã®ã‚¯ãƒ©ã‚¹ã¯UNIX標準ã®DBMã¨åŒæ§˜ã®æ©Ÿèƒ½ã‚’æŒã¤ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒžãƒãƒ¼ã‚¸ãƒ£ã‚’抽象化ã—ãŸã‚¤ãƒ³ã‚¿ãƒ•ェースã§ã‚りã€ç´”粋仮想関数ã®å®£è¨€ã®ã¿ã‚’行ã†ã€‚å„メンãƒé–¢æ•°ã¯ã‚¨ãƒ©ãƒ¼æ™‚ã«ã‚¯ãƒ©ã‚¹ `DBM_error' ã®ã‚¤ãƒ³ã‚¹ã‚¿ãƒ³ã‚¹ã‚’投ã’る。ã“ã®ãƒ•レームワークã§ã¯ã€ãƒ¬ã‚³ãƒ¼ãƒ‰ã®ã‚­ãƒ¼ã‚„値ã¯ã‚¯ãƒ©ã‚¹ `Datum' ã¨ã—ã¦è¡¨ç¾ã•れる。`Datum' ã®ã‚¤ãƒ³ã‚¹ã‚¿ãƒ³ã‚¹ã¯ãƒ‡ãƒ¼ã‚¿é ˜åŸŸã®ãƒã‚¤ãƒ³ã‚¿ã¨ãã®ã‚µã‚¤ã‚ºã‚’æŒã¤ã€‚å››ã¤ã®APIã‹ã‚‰é©åˆ‡ãªã‚‚ã®ã‚’é¸æŠžã™ã‚‹éš›ã«ã¯ã€å®Ÿè¡ŒåŠ¹çŽ‡ã‚’é‡è¦–ã™ã‚‹ãªã‚‰ `Depot' ã‚’ã€ã‚¹ã‚±ãƒ¼ãƒ©ãƒ“リティをé‡è¦–ã™ã‚‹ãªã‚‰ `Curia' ã‚’ã€é †åºã«åŸºã¥ãå‚ç…§ãŒå¿…è¦ãªã‚‰ `Villa' ã‚’ã€ã‚¨ãƒ¬ã‚¬ãƒ³ã‚¹ã¨ä¿å®ˆæ€§ã‚’é‡è¦–ã™ã‚‹ãªã‚‰ `ADBM' ã‚’é¸ã¶ã¹ãã§ã‚ã‚ã†ã€‚データベースファイルã¯å„APIã®é–“ã§äº’æ›æ€§ãŒãªã„。

アプリケーションã®ã‚½ãƒ¼ã‚¹ãƒ•ァイルã«ãŠã„ã¦ã€`Depot' を用ã„ã‚‹ã«ã¯ `xdepot.h' ã‚’ã€`Curia' を用ã„ã‚‹ã«ã¯ `xcuria.h' ã‚’ã€`Villa' を用ã„ã‚‹ã«ã¯ `xvilla.h' ã‚’ã€`ADBM' を用ã„ã‚‹ã«ã¯ `xadbm.h' をインクルードã™ã‚‹å¿…è¦ãŒã‚る。å„クラスã¯åå‰ç©ºé–“ `qdbm' ã«ãƒ‘ッケージã•れã¦ã„る。

C言語ã®APIã¯ã€ã‚¹ãƒ¬ãƒƒãƒ‰é–“ã§ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒãƒ³ãƒ‰ãƒ«ã‚’共有ã—ãªã„é™ã‚Šã¯ã‚¹ãƒ¬ãƒƒãƒ‰ã‚»ãƒ¼ãƒ•ã§ã‚る。C++ã®APIã§ã¯ã€è¤‡æ•°ã®ã‚¹ãƒ¬ãƒƒãƒ‰ãŒåŒã˜ãƒãƒ³ãƒ‰ãƒ«ã«ã‚¢ã‚¯ã‚»ã‚¹ã—ã¦ã‚‚スレッドセーフã§ã‚る。ã“ã®APIã¯POSIXã‚¹ãƒ¬ãƒƒãƒ‰ãƒ‘ãƒƒã‚±ãƒ¼ã‚¸ã‚’å‰æã¨ã—ã¦å®Ÿè£…ã•れã¦ã„る。別ã®ã‚¹ãƒ¬ãƒƒãƒ‰ãƒ‘ッケージを用ã„ã‚‹å ´åˆã¯ã€ç‹¬è‡ªã®C++用ラッパを書ãã¹ãã§ã‚る。

`put' ã§æ—¢å­˜ã®ãƒ¬ã‚³ãƒ¼ãƒ‰ã®ä¸Šæ›¸ããŒã‚­ãƒ£ãƒ³ã‚»ãƒ«ã•れãŸéš›ã‚„ `get' ã§å­˜åœ¨ã—ãªã„ãƒ¬ã‚³ãƒ¼ãƒ‰ãŒæ¤œç´¢ã•れãŸéš›ã«ã¯ä¾‹å¤–ã«ã‚ˆã£ã¦æ“作ã®å¤±æ•—ãŒé€šçŸ¥ã•れるãŒã€ãれãŒé¬±é™¶ã—ã„å ´åˆã¯ `silent' フラグを真ã«ã™ã‚‹ã¨ã‚ˆã„。ãã®å ´åˆã¯å¤±æ•—ãŒæˆ»ã‚Šå€¤ã«ã‚ˆã£ã¦é€šçŸ¥ã•れる。

APIã®è©³ç´°ã«é–¢ã—ã¦ã¯ã€ã‚µãƒ–ディレクトリ `xapidoc' ã®æ–‡æ›¸ã¨å„ヘッダファイルをå‚ç…§ã™ã‚‹ã“ã¨ã€‚


インストール

準備

GCCã®3.3以é™ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ãŒã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•れã€QDBM㌠`/usr/local' 以下ã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•れã¦ã„ã‚‹ã“ã¨ãŒå¿…è¦ã§ã‚る。

インストール作業ã¯ã€ã‚µãƒ–ディレクトリ `plus' をカレントディレクトリã«ã—ã¦è¡Œã†ã€‚

cd plus

æ™®é€šã®æ‰‹é †

ビルド環境を設定ã™ã‚‹ã€‚

./configure

プログラムをビルドã™ã‚‹ã€‚

make

プログラムã®è‡ªå·±è¨ºæ–­ãƒ†ã‚¹ãƒˆã‚’行ã†ã€‚

make check

プログラムをインストールã™ã‚‹ã€‚作業㯠`root' ユーザã§è¡Œã†ã€‚

make install

一連ã®ä½œæ¥­ãŒçµ‚ã‚‹ã¨ã€ãƒ˜ãƒƒãƒ€ãƒ•ァイル `xdepot.h' 㨠`xcuria.h' 㨠`xvilla.h' 㨠`xadbm.h' ㌠`/usr/local/include' ã«ã€ãƒ©ã‚¤ãƒ–ラリ `libxqdbm.so' 等㌠`/usr/local/lib' ã«ã€ã‚³ãƒžãƒ³ãƒ‰ `xdptest' 㨠`xcrtest' 㨠`xvltest' ㌠`/usr/local/bin' ã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•れる。

アンインストールã™ã‚‹ã«ã¯ã€`./configure' ã‚’ã—ãŸå¾Œã®çŠ¶æ…‹ã§ä»¥ä¸‹ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹ã€‚作業㯠`root' ユーザã§è¡Œã†ã€‚

make uninstall

Windowsã®å ´åˆ

Windows(Cygwin)ã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã™ã‚‹å ´åˆã€ä»¥ä¸‹ã®æ‰‹é †ã«å¾“ã†ã€‚

ビルド環境を設定ã™ã‚‹ã€‚

./configure

プログラムをビルドã™ã‚‹ã€‚

make win

プログラムã®è‡ªå·±è¨ºæ–­ãƒ†ã‚¹ãƒˆã‚’行ã†ã€‚

make check-win

プログラムをインストールã™ã‚‹ã€‚ãªãŠã€ã‚¢ãƒ³ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã™ã‚‹å ´åˆã¯ `make uninstall-win' ã¨ã™ã‚‹ã€‚

make install-win

Windowsã§ã¯ã€é™çš„ライブラリ `libxqdbm.a' ã®ä»£ã‚りã«ã‚¤ãƒ³ãƒãƒ¼ãƒˆãƒ©ã‚¤ãƒ–ラリ `libxqdbm.dll.a' ãŒç”Ÿæˆã•れã€ã•らã«ãƒ€ã‚¤ãƒŠãƒŸãƒƒã‚¯ãƒªãƒ³ã‚¯ãƒ©ã‚¤ãƒ–ラリ `xqdbm.dll' ãŒç”Ÿæˆã•れる。`xqdbm.dll' 㯠`/usr/local/bin' ã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•れる。

C++用ã®APIã§ã¯MinGWを用ã„ãŸãƒ“ルドã¯ã‚µãƒãƒ¼ãƒˆã•れãªã„。

Mac OS Xã®å ´åˆ

Mac OS X(Darwin)ã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã™ã‚‹å ´åˆã€ä»¥ä¸‹ã®æ‰‹é †ã«å¾“ã†ã€‚

ビルド環境を設定ã™ã‚‹ã€‚

./configure

プログラムをビルドã™ã‚‹ã€‚

make mac

プログラムã®è‡ªå·±è¨ºæ–­ãƒ†ã‚¹ãƒˆã‚’行ã†ã€‚

make check-mac

プログラムをインストールã™ã‚‹ã€‚ãªãŠã€ã‚¢ãƒ³ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã™ã‚‹å ´åˆã¯ `make uninstall-mac' ã¨ã™ã‚‹ã€‚

make install-mac

Mac OS Xã§ã¯ã€`libxqdbm.so' ç­‰ã®ä»£ã‚り㫠`libxqdbm.dylib' ç­‰ãŒç”Ÿæˆã•れる。

HP-UXã®å ´åˆ

HP-UXã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã™ã‚‹å ´åˆã€ä»¥ä¸‹ã®æ‰‹é †ã«å¾“ã†ã€‚

ビルド環境を設定ã™ã‚‹ã€‚

./configure

プログラムをビルドã™ã‚‹ã€‚

make hpux

プログラムã®è‡ªå·±è¨ºæ–­ãƒ†ã‚¹ãƒˆã‚’行ã†ã€‚

make check-hpux

プログラムをインストールã™ã‚‹ã€‚ãªãŠã€ã‚¢ãƒ³ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã™ã‚‹å ´åˆã¯ `make uninstall-hpux' ã¨ã™ã‚‹ã€‚

make install-hpux

HP-UXã§ã¯ã€`libxqdbm.so' ç­‰ã®ä»£ã‚り㫠`libxqdbm.sl' ãŒç”Ÿæˆã•れる。


サンプルコード

åå‰ã¨å¯¾å¿œã•ã›ã¦é›»è©±ç•ªå·ã‚’æ ¼ç´ã—ã€ãれを検索ã™ã‚‹ã‚¢ãƒ—リケーションã®ã‚µãƒ³ãƒ—ルコードを以下ã«ç¤ºã™ã€‚

#include <xdepot.h>
#include <cstdlib>
#include <iostream>

using namespace std;
using namespace qdbm;

const char* NAME = "mikio";
const char* NUMBER = "000-1234-5678";
const char* DBNAME = "book";

int main(int argc, char** argv){
  try {

    // データベースを開ã
    Depot depot(DBNAME, Depot::OWRITER | Depot::OCREAT);

    // レコードを格ç´ã™ã‚‹
    depot.put(NAME, -1, NUMBER, -1);

    // レコードをå–å¾—ã™ã‚‹
    char* val = depot.get(NAME, -1);
    cout << "Name: " << NAME << endl;
    cout << "Number: " << val << endl;
    free(val);

    // データベースを閉ã˜ã‚‹
    depot.close();

  } catch(Depot_error& e){
    cerr << e << endl;
    return 1;
  }
  return 0;
}

上記ã®ä¾‹ã‚’ `ADBM' クラスを用ã„ã¦æ›¸ãç›´ã—ãŸä¾‹ã‚’以下ã«ç¤ºã™ã€‚

#include <xadbm.h>
#include <xdepot.h>
#include <iostream>

using namespace std;
using namespace qdbm;

const char* NAME = "mikio";
const char* NUMBER = "000-1234-5678";
const char* DBNAME = "book";

int main(int argc, char** argv){
  try {

    // データベースを開ã
    Depot depot(DBNAME, Depot::OWRITER | Depot::OCREAT);
    ADBM& dbm = depot;

    // レコードを準備ã™ã‚‹
    Datum key(NAME);
    Datum val(NUMBER);

    // レコードを格ç´ã™ã‚‹
    dbm.storerec(key, val);

    // レコードをå–å¾—ã™ã‚‹
    const Datum& res = dbm.fetchrec(key);
    cout << "Name: " << NAME << endl;
    cout << "Number: " << res << endl;

    // データベースを閉ã˜ã‚‹
    dbm.close();

  } catch(DBM_error& e){
    cerr << e << endl;
    return 1;
  }
  return 0;
}

`Villa' クラスを用ã„ã¦æ–‡å­—列ã®å‰æ–¹ä¸€è‡´æ¤œç´¢ã‚’行ã†ä¾‹ã‚’以下ã«ç¤ºã™ã€‚

#include <xvilla.h>
#include <cstdlib>
#include <cstring>
#include <iostream>

using namespace std;
using namespace qdbm;

const char* DBNAME = "words";
const char* PREFIX = "apple";

int main(int argc, char** argv){
  try {

    // データベースを開ã
    Villa villa(DBNAME, Villa::OWRITER | Villa::OCREAT);

    // レコードを格ç´ã™ã‚‹
    villa.put("applet", -1, "little application", -1, Villa::DDUP);
    villa.put("aurora", -1, "polar wonderwork", -1, Villa::DDUP);
    villa.put("apple", -1, "delicious fruit", -1, Villa::DDUP);
    villa.put("amigo", -1, "good friend", -1, Villa::DDUP);
    villa.put("apple", -1, "big city", -1, Villa::DDUP);

    try {

      // カーソルを候補ã®å…ˆé ­ã«ç½®ã
      villa.curjump(PREFIX, -1);

      // カーソルを走査ã™ã‚‹
      for(;;){
        char* key = villa.curkey();
        if(strstr(key, PREFIX) != key){
          free(key);
          break;
        }
        char* val = villa.curval();
        cout << key << ": " << val << endl;
        free(key);
        free(val);
        villa.curnext();
      }

    } catch(Villa_error& e){
      if(e.code() != Villa::ENOITEM) throw e;
    }

    // データベースを閉ã˜ã‚‹
    villa.close();

  } catch(Villa_error& e){
    cerr << e << endl;
    return 1;
  }
  return 0;
}

C++用APIを利用ã—ãŸãƒ—ログラムをビルドã™ã‚‹ã«ã¯ã€ãƒ©ã‚¤ãƒ–ラリ `xqdbm' 㨠`qdbm' をリンク対象ã«åŠ ãˆã‚‹å¿…è¦ãŒã‚る。例ãˆã°ã€`sample.cc' ã‹ã‚‰ `sample' を作るã«ã¯ã€ä»¥ä¸‹ã®ã‚ˆã†ã«ãƒ“ルドを行ã†ã€‚

g++ -I/usr/local/include -o sample sample.cc -L/usr/local/lib -lxqdbm -lqdbm

ãƒã‚°

ã²ã¨ã¤ã®ãƒ—ロセスã§è¤‡æ•°ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ã‚¡ã‚¤ãƒ«ã‚’åŒæ™‚ã«åˆ©ç”¨ã™ã‚‹ã“ã¨ã¯å¯èƒ½ã§ã‚ã‚‹ãŒã€åŒã˜ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ãƒ•ァイルã®è¤‡æ•°ã®ãƒãƒ³ãƒ‰ãƒ«ã‚’利用ã—ã¦ã¯ãªã‚‰ãªã„。ã²ã¨ã¤ã®ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã‚’複数ã®ã‚¹ãƒ¬ãƒƒãƒ‰ã§åˆ©ç”¨ã™ã‚‹å ´åˆã«ã¯ã€ãƒ¡ã‚¤ãƒ³ã‚¹ãƒ¬ãƒƒãƒ‰ã§ç”Ÿæˆã—ãŸãƒãƒ³ãƒ‰ãƒ«ã‚’ä»–ã®ã‚¹ãƒ¬ãƒƒãƒ‰ã«æ¸¡ã›ã°ã‚ˆã„。

一般的ãªã‚ªãƒ–ジェクトを直列化ã—ã¦ãƒ‡ãƒ¼ã‚¿ãƒ™ãƒ¼ã‚¹ã«æ ¼ç´ã™ã‚‹ä»•組ã¿ã¯ãªã„ã®ã§ã€å¿…è¦ãªã‚‰ã°ã€`Datum' クラスを拡張ã—ã¦ãã®ä»•組ã¿ã‚’作ã£ã¦ã»ã—ã„。ã¾ãŸã€`Villa' ã®æ¯”較関数ã§ã€ç›´åˆ—化ã—ãŸã‚ªãƒ–ジェクトを復元ã—ãŸä¸Šã§æ¯”較ã™ã‚‹ã‚ˆã†ã«ã™ã‚Œã°ã€ã‚ˆã‚Šã‚ªãƒ–ジェクト指å‘データベースらã—ããªã‚‹ã ã‚ã†ã€‚


qdbm-1.8.78/plus/xvilla.cc0000644000175000017500000003635310505716641014354 0ustar mikiomikio/************************************************************************************************* * Implementation of Villa for C++ * Copyright (C) 2000-2005 Mikio Hirabayashi * This file is part of QDBM, Quick Database Manager. * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU * Lesser General Public License as published by the Free Software Foundation; either version * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * You should have received a copy of the GNU Lesser General Public License along with QDBM; if * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. *************************************************************************************************/ #include "xvilla.h" #include #include #include extern "C" { #include #include #include #include } using namespace qdbm; /************************************************************************************************* * Villa_error *************************************************************************************************/ Villa_error::Villa_error() throw() : DBM_error(){ ecode = DP_EMISC; return; } Villa_error::Villa_error(int ecode) throw() : DBM_error(){ this->ecode = ecode; return; } Villa_error::Villa_error(const Villa_error& ve) throw() : DBM_error(ve){ ecode = ve.ecode; return; } Villa_error::~Villa_error() throw(){ return; } Villa_error& Villa_error::operator =(const Villa_error& ve) throw(){ this->ecode = ve.ecode; return *this; } Villa_error& Villa_error::operator =(int ecode) throw(){ this->ecode = ecode; return *this; } bool Villa_error::operator ==(const Villa_error& ve) const throw(){ return ecode == ve.ecode; } bool Villa_error::operator !=(const Villa_error& ve) const throw(){ return ecode != ve.ecode; } bool Villa_error::operator ==(int ecode) const throw(){ return this->ecode == ecode; } bool Villa_error::operator !=(int ecode) const throw(){ return this->ecode != ecode; } Villa_error::operator const char*() const throw(){ return dperrmsg(ecode); } int Villa_error::code() const throw(){ return ecode; } const char* Villa_error::message() const throw(){ return dperrmsg(ecode); } /************************************************************************************************* * Villa *************************************************************************************************/ const int Villa::ENOERR = DP_ENOERR; const int Villa::EFATAL = DP_EFATAL; const int Villa::EMODE = DP_EMODE; const int Villa::EBROKEN = DP_EBROKEN; const int Villa::EKEEP = DP_EKEEP; const int Villa::ENOITEM = DP_ENOITEM; const int Villa::EALLOC = DP_EALLOC; const int Villa::EMAP = DP_EMAP; const int Villa::EOPEN = DP_EOPEN; const int Villa::ECLOSE = DP_ECLOSE; const int Villa::ETRUNC = DP_ETRUNC; const int Villa::ESYNC = DP_ESYNC; const int Villa::ESTAT = DP_ESTAT; const int Villa::ESEEK = DP_ESEEK; const int Villa::EREAD = DP_EREAD; const int Villa::EWRITE = DP_EWRITE; const int Villa::ELOCK = DP_ELOCK; const int Villa::EUNLINK = DP_EUNLINK; const int Villa::EMKDIR = DP_EMKDIR; const int Villa::ERMDIR = DP_ERMDIR; const int Villa::EMISC = DP_EMISC; const int Villa::OREADER = VL_OREADER; const int Villa::OWRITER = VL_OWRITER; const int Villa::OCREAT = VL_OCREAT; const int Villa::OTRUNC = VL_OTRUNC; const int Villa::ONOLCK = VL_ONOLCK; const int Villa::OLCKNB = VL_OLCKNB; const int Villa::OZCOMP = VL_OZCOMP; const int Villa::OYCOMP = VL_OYCOMP; const int Villa::OXCOMP = VL_OXCOMP; const int Villa::DOVER = VL_DOVER; const int Villa::DKEEP = VL_DKEEP; const int Villa::DCAT = VL_DCAT; const int Villa::DDUP = VL_DDUP; const int Villa::DDUPR = VL_DDUPR; const int Villa::JFORWARD = VL_JFORWARD; const int Villa::JBACKWARD = VL_JBACKWARD; const int Villa::CPCURRENT = VL_CPCURRENT; const int Villa::CPBEFORE = VL_CPBEFORE; const int Villa::CPAFTER = VL_CPAFTER; const char* Villa::version() throw(){ return dpversion; } void Villa::remove(const char* name) throw(Villa_error){ if(pthread_mutex_lock(&ourmutex) != 0) throw Villa_error(); if(!vlremove(name)){ int ecode = dpecode; pthread_mutex_unlock(&ourmutex); throw Villa_error(ecode); } pthread_mutex_unlock(&ourmutex); } int Villa::cmplex(const char *aptr, int asiz, const char *bptr, int bsiz) throw(){ return VL_CMPLEX(aptr, asiz, bptr, bsiz); } int Villa::cmpint(const char *aptr, int asiz, const char *bptr, int bsiz) throw(){ return VL_CMPINT(aptr, asiz, bptr, bsiz); } int Villa::cmpnum(const char *aptr, int asiz, const char *bptr, int bsiz) throw(){ return VL_CMPNUM(aptr, asiz, bptr, bsiz); } int Villa::cmpdec(const char *aptr, int asiz, const char *bptr, int bsiz) throw(){ return VL_CMPDEC(aptr, asiz, bptr, bsiz); } Villa::Villa(const char* name, int omode, VLCFUNC cmp) throw(Villa_error) : ADBM(){ pthread_mutex_init(&mymutex, NULL); silent = false; if(!lock()) throw Villa_error(); if(!(villa = vlopen(name, omode, cmp))){ int ecode = dpecode; unlock(); throw Villa_error(ecode); } pthread_mutex_init(&tranmutex, NULL); unlock(); } Villa::~Villa() throw(){ pthread_mutex_destroy(&tranmutex); if(!villa){ pthread_mutex_destroy(&mymutex); return; } if(lock()){ vlclose(villa); unlock(); } villa = 0; pthread_mutex_destroy(&mymutex); } void Villa::close() throw(Villa_error){ if(!villa) throw Villa_error(); if(!lock()) throw Villa_error(); if(!vlclose(villa)){ int ecode = dpecode; villa = 0; unlock(); throw Villa_error(ecode); } villa = 0; unlock(); } bool Villa::put(const char* kbuf, int ksiz, const char* vbuf, int vsiz, int dmode) throw(Villa_error){ if(!villa) throw Villa_error(); if(!lock()) throw Villa_error(); if(!vlput(villa, kbuf, ksiz, vbuf, vsiz, dmode)){ int ecode = dpecode; unlock(); if(silent && ecode == EKEEP) return false; throw Villa_error(ecode); } unlock(); return true; } bool Villa::out(const char* kbuf, int ksiz) throw(Villa_error){ if(!villa) throw Villa_error(); if(!lock()) throw Villa_error(); if(!vlout(villa, kbuf, ksiz)){ int ecode = dpecode; unlock(); if(silent && ecode == ENOITEM) return false; throw Villa_error(ecode); } unlock(); return true; } char* Villa::get(const char* kbuf, int ksiz, int* sp) throw(Villa_error){ char* vbuf; if(!villa) throw Villa_error(); if(!lock()) throw Villa_error(); if(!(vbuf = vlget(villa, kbuf, ksiz, sp))){ int ecode = dpecode; unlock(); if(silent && ecode == ENOITEM) return 0; throw Villa_error(ecode); } unlock(); return vbuf; } int Villa::vsiz(const char *kbuf, int ksiz) throw(Villa_error){ int vsiz; if(!villa) throw Villa_error(); if(!lock()) throw Villa_error(); if((vsiz = vlvsiz(villa, kbuf, ksiz)) == -1){ int ecode = dpecode; unlock(); if(silent && ecode == ENOITEM) return 0; throw Villa_error(ecode); } unlock(); return vsiz; } int Villa::vnum(const char *kbuf, int ksiz) throw(Villa_error){ int vnum; if(!villa) throw Villa_error(); if(!lock()) throw Villa_error(); vnum = vlvnum(villa, kbuf, ksiz); unlock(); return vnum; } bool Villa::curfirst() throw(Villa_error){ if(!villa) throw Villa_error(); if(!lock()) throw Villa_error(); if(!vlcurfirst(villa)){ int ecode = dpecode; unlock(); if(silent && ecode == ENOITEM) return 0; throw Villa_error(ecode); } unlock(); return true; } bool Villa::curlast() throw(Villa_error){ if(!villa) throw Villa_error(); if(!lock()) throw Villa_error(); if(!vlcurlast(villa)){ int ecode = dpecode; unlock(); if(silent && ecode == ENOITEM) return 0; throw Villa_error(ecode); } unlock(); return true; } bool Villa::curprev() throw(Villa_error){ if(!villa) throw Villa_error(); if(!lock()) throw Villa_error(); if(!vlcurprev(villa)){ int ecode = dpecode; unlock(); if(silent && ecode == ENOITEM) return 0; throw Villa_error(ecode); } unlock(); return true; } bool Villa::curnext() throw(Villa_error){ if(!villa) throw Villa_error(); if(!lock()) throw Villa_error(); if(!vlcurnext(villa)){ int ecode = dpecode; unlock(); if(silent && ecode == ENOITEM) return 0; throw Villa_error(ecode); } unlock(); return true; } bool Villa::curjump(const char* kbuf, int ksiz, int jmode) throw(Villa_error){ if(!villa) throw Villa_error(); if(!lock()) throw Villa_error(); if(!vlcurjump(villa, kbuf, ksiz, jmode)){ int ecode = dpecode; unlock(); if(silent && ecode == ENOITEM) return 0; throw Villa_error(ecode); } unlock(); return true; } char* Villa::curkey(int *sp) throw(Villa_error){ char* kbuf; if(!villa) throw Villa_error(); if(!lock()) throw Villa_error(); if(!(kbuf = vlcurkey(villa, sp))){ int ecode = dpecode; unlock(); if(silent && ecode == ENOITEM) return 0; throw Villa_error(ecode); } unlock(); return kbuf; } char* Villa::curval(int *sp) throw(Villa_error){ char* vbuf; if(!villa) throw Villa_error(); if(!lock()) throw Villa_error(); if(!(vbuf = vlcurval(villa, sp))){ int ecode = dpecode; unlock(); if(silent && ecode == ENOITEM) return 0; throw Villa_error(ecode); } unlock(); return vbuf; } bool Villa::curput(const char* vbuf, int vsiz, int cpmode) throw(Villa_error){ if(!villa) throw Villa_error(); if(!lock()) throw Villa_error(); if(!vlcurput(villa, vbuf, vsiz, cpmode)){ int ecode = dpecode; unlock(); if(silent && ecode == ENOITEM) return false; throw Villa_error(ecode); } unlock(); return true; } bool Villa::curout() throw(Villa_error){ if(!villa) throw Villa_error(); if(!lock()) throw Villa_error(); if(!vlcurout(villa)){ int ecode = dpecode; unlock(); if(silent && ecode == ENOITEM) return false; throw Villa_error(ecode); } unlock(); return true; } void Villa::settuning(int lrecmax, int nidxmax, int lcnum, int ncnum) throw(Villa_error){ if(!villa) throw Villa_error(); if(!lock()) throw Villa_error(); vlsettuning(villa, lrecmax, nidxmax, lcnum, ncnum); unlock(); } void Villa::sync() throw(Villa_error){ if(!villa) throw Villa_error(); if(!lock()) throw Villa_error(); if(!vlsync(villa)){ int ecode = dpecode; unlock(); throw Villa_error(ecode); } unlock(); } void Villa::optimize() throw(Villa_error){ if(!villa) throw Villa_error(); if(!lock()) throw Villa_error(); if(!vloptimize(villa)){ int ecode = dpecode; unlock(); throw Villa_error(ecode); } unlock(); } char* Villa::name() throw(Villa_error){ char* buf; if(!villa) throw Villa_error(); if(!lock()) throw Villa_error(); if(!(buf = vlname(villa))){ int ecode = dpecode; unlock(); throw Villa_error(ecode); } unlock(); return buf; } int Villa::fsiz() throw(Villa_error){ int rv; if(!villa) throw Villa_error(); if(!lock()) throw Villa_error(); if((rv = vlfsiz(villa)) == -1){ int ecode = dpecode; unlock(); throw Villa_error(ecode); } unlock(); return rv; } int Villa::lnum() throw(Villa_error){ int rv; if(!villa) throw Villa_error(); if(!lock()) throw Villa_error(); if((rv = vllnum(villa)) == -1){ int ecode = dpecode; unlock(); throw Villa_error(ecode); } unlock(); return rv; } int Villa::nnum() throw(Villa_error){ int rv; if(!villa) throw Villa_error(); if(!lock()) throw Villa_error(); if((rv = vlnnum(villa)) == -1){ int ecode = dpecode; unlock(); throw Villa_error(ecode); } unlock(); return rv; } int Villa::rnum() throw(Villa_error){ int rv; if(!villa) throw Villa_error(); if(!lock()) throw Villa_error(); if((rv = vlrnum(villa)) == -1){ int ecode = dpecode; unlock(); throw Villa_error(ecode); } unlock(); return rv; } bool Villa::writable() throw(Villa_error){ int rv; if(!villa) throw Villa_error(); if(!lock()) throw Villa_error(); rv = vlwritable(villa); unlock(); return rv ? true : false; } bool Villa::fatalerror() throw(Villa_error){ int rv; if(!villa) throw Villa_error(); if(!lock()) throw Villa_error(); rv = vlfatalerror(villa); unlock(); return rv ? true : false; } int Villa::inode() throw(Villa_error){ int rv; if(!villa) throw Villa_error(); if(!lock()) throw Villa_error(); rv = vlinode(villa); unlock(); return rv; } time_t Villa::mtime() throw(Villa_error){ time_t rv; if(!villa) throw Villa_error(); if(!lock()) throw Villa_error(); rv = vlmtime(villa); unlock(); return rv; } void Villa::tranbegin() throw(Villa_error){ if(!villa) throw Villa_error(); if(pthread_mutex_lock(&tranmutex) != 0) throw Villa_error(); if(!lock()){ pthread_mutex_unlock(&tranmutex); throw Villa_error(); } if(!vltranbegin(villa)){ int ecode = dpecode; unlock(); pthread_mutex_unlock(&tranmutex); throw Villa_error(ecode); } unlock(); } void Villa::trancommit() throw(Villa_error){ if(!villa) throw Villa_error(); if(!lock()) throw Villa_error(); if(!vltrancommit(villa)){ int ecode = dpecode; unlock(); pthread_mutex_unlock(&tranmutex); throw Villa_error(ecode); } unlock(); if(pthread_mutex_unlock(&tranmutex) != 0) throw Villa_error(); } void Villa::tranabort() throw(Villa_error){ if(!villa) throw Villa_error(); if(!lock()) throw Villa_error(); if(!vltranabort(villa)){ int ecode = dpecode; unlock(); pthread_mutex_unlock(&tranmutex); throw Villa_error(ecode); } unlock(); if(pthread_mutex_unlock(&tranmutex) != 0) throw Villa_error(); } void Villa::storerec(const Datum& key, const Datum& val, bool replace) throw(Villa_error){ if(!put(key.ptr(), key.size(), val.ptr(), val.size(), replace ? VL_DOVER : VL_DKEEP)) throw Villa_error(EKEEP); } void Villa::deleterec(const Datum& key) throw(Villa_error){ if(!out(key.ptr(), key.size())) throw Villa_error(ENOITEM); } Datum Villa::fetchrec(const Datum& key) throw(Villa_error){ char* vbuf; int vsiz; vbuf = get(key.ptr(), key.size(), &vsiz); if(!vbuf) throw Villa_error(ENOITEM); return Datum(vbuf, vsiz, true); } Datum Villa::firstkey() throw(Villa_error){ char* kbuf; int ksiz; curfirst(); kbuf = curkey(&ksiz); if(!kbuf) throw Villa_error(ENOITEM); return Datum(kbuf, ksiz, true); } Datum Villa::nextkey() throw(Villa_error){ char* kbuf; int ksiz; curnext(); kbuf = curkey(&ksiz); if(!kbuf) throw Villa_error(ENOITEM); return Datum(kbuf, ksiz, true); } bool Villa::error() throw(Villa_error){ return fatalerror(); } Villa::Villa(const Villa& villa) throw(Villa_error){ throw Villa_error(); } Villa& Villa::operator =(const Villa& villa) throw(Villa_error){ throw Villa_error(); } bool Villa::lock(){ if(dpisreentrant){ if(pthread_mutex_lock(&mymutex) != 0) return false; return true; } if(pthread_mutex_lock(&ourmutex) != 0) return false; return true; } void Villa::unlock(){ if(dpisreentrant){ pthread_mutex_unlock(&mymutex); } else { pthread_mutex_unlock(&ourmutex); } } /* END OF FILE */ qdbm-1.8.78/plus/xapidoc/0000755000175000017500000000000011426320062014152 5ustar mikiomikioqdbm-1.8.78/plus/xapidoc/classqdbm_1_1Depot-members.html0000644000175000017500000004113411426320062022100 0ustar mikiomikio QDBM for C++: Member List

qdbm::Depot Member List

This is the complete list of members for qdbm::Depot, including all inherited members.
bnum()qdbm::Depot [virtual]
busenum()qdbm::Depot [virtual]
close()qdbm::Depot [virtual]
DCATqdbm::Depot [static]
deleterec(const Datum &key)qdbm::Depot [virtual]
Depot(const char *name, int omode=Depot::OREADER, int bnum=-1)qdbm::Depot
DKEEPqdbm::Depot [static]
DOVERqdbm::Depot [static]
EALLOCqdbm::Depot [static]
EBROKENqdbm::Depot [static]
ECLOSEqdbm::Depot [static]
EFATALqdbm::Depot [static]
EKEEPqdbm::Depot [static]
ELOCKqdbm::Depot [static]
EMAPqdbm::Depot [static]
EMISCqdbm::Depot [static]
EMKDIRqdbm::Depot [static]
EMODEqdbm::Depot [static]
ENOERRqdbm::Depot [static]
ENOITEMqdbm::Depot [static]
EOPENqdbm::Depot [static]
EREADqdbm::Depot [static]
ERMDIRqdbm::Depot [static]
error()qdbm::Depot [virtual]
ESEEKqdbm::Depot [static]
ESTATqdbm::Depot [static]
ESYNCqdbm::Depot [static]
ETRUNCqdbm::Depot [static]
EUNLINKqdbm::Depot [static]
EWRITEqdbm::Depot [static]
fatalerror()qdbm::Depot [virtual]
fdesc()qdbm::Depot [virtual]
fetchrec(const Datum &key)qdbm::Depot [virtual]
firstkey()qdbm::Depot [virtual]
fsiz()qdbm::Depot [virtual]
get(const char *kbuf, int ksiz, int start=0, int max=-1, int *sp=0)qdbm::Depot [virtual]
getwb(const char *kbuf, int ksiz, int start, int max, char *vbuf)qdbm::Depot [virtual]
inode()qdbm::Depot [virtual]
iterinit()qdbm::Depot [virtual]
iternext(int *sp=0)qdbm::Depot [virtual]
mtime()qdbm::Depot [virtual]
name()qdbm::Depot [virtual]
nextkey()qdbm::Depot [virtual]
OCREATqdbm::Depot [static]
OLCKNBqdbm::Depot [static]
ONOLCKqdbm::Depot [static]
optimize(int bnum=-1)qdbm::Depot [virtual]
OREADERqdbm::Depot [static]
OSPARSEqdbm::Depot [static]
OTRUNCqdbm::Depot [static]
out(const char *kbuf, int ksiz)qdbm::Depot [virtual]
OWRITERqdbm::Depot [static]
put(const char *kbuf, int ksiz, const char *vbuf, int vsiz, int dmode=Depot::DOVER)qdbm::Depot [virtual]
remove(const char *name)qdbm::Depot [static]
rnum()qdbm::Depot [virtual]
setalign(int align)qdbm::Depot [virtual]
setfbpsiz(int size)qdbm::Depot [virtual]
silentqdbm::Depot
snaffle(const char *name, const char *kbuf, int ksiz, int *sp)qdbm::Depot [static]
storerec(const Datum &key, const Datum &val, bool replace=true)qdbm::Depot [virtual]
sync()qdbm::Depot [virtual]
version()qdbm::Depot [static]
vsiz(const char *kbuf, int ksiz)qdbm::Depot [virtual]
writable()qdbm::Depot [virtual]
~ADBM()qdbm::ADBM [virtual]
~Depot()qdbm::Depot [virtual]
Generated on Thu Aug 5 02:15:30 2010 for QDBM for C++ by  doxygen 1.6.3
qdbm-1.8.78/plus/xapidoc/functions_vars.html0000644000175000017500000003173511426320062020114 0ustar mikiomikio QDBM for C++: Class Members - Variables
 

- c -

- d -

- e -

- j -

- o -

- s -

Generated on Thu Aug 5 02:15:30 2010 for QDBM for C++ by  doxygen 1.6.3
qdbm-1.8.78/plus/xapidoc/tab_b.gif0000644000175000017500000000004311426320062015705 0ustar mikiomikioGIF89a€„°Ç,D;qdbm-1.8.78/plus/xapidoc/classqdbm_1_1Villa__error.png0000644000175000017500000000112311426320062021626 0ustar mikiomikio‰PNG  IHDRoP 7Û*PLTEÿÿÿÿÿÀŸŸ`ÀÀÀ{ÂÿätRNSÿÿÿÿÿÿÿÕÊT2âIDATxíÑnì DgŒ”ÿÿä>ŒmLBïÍF R+6,àø Æ¯ðÖ¼­›™-éãÄ[‡3 ­ÄYC[‰ƒxÃ4Í85'IÂüÉ ¥¿mh·NÍ Á1šQvœË›öÍsԌҤš1Íå6äРÝÖ€¤ ¢Dé2åÇ[¼î¢©˜’æü²k *¤Gnç²$—0ɆIF©?†*ÈÿcŽ‘©{Ö³—û°gé‡ú‹÷®ÊwêåÖåäzŒ‡”ò †ÛžRYRåËëÞ2X)'×cê†çsºîoÎ;ªÉ'¼0âYœùè=Þ5žÙßà]Ïï’‡“’xÏy~ž©'Æ/~¦c>ÊĤþÞÿÖü/®¶U¼}?lÞ{¼µí å8•.°IEND®B`‚qdbm-1.8.78/plus/xapidoc/functions_0x65.html0000644000175000017500000002353511426320062017642 0ustar mikiomikio QDBM for C++: Class Members
Generated on Thu Aug 5 02:15:30 2010 for QDBM for C++ by  doxygen 1.6.3
qdbm-1.8.78/plus/xapidoc/classes.html0000644000175000017500000000730711426320062016504 0ustar mikiomikio QDBM for C++: Alphabetical List

Class Index

A | C | D | V
  A  
Curia (qdbm)   Datum (qdbm)   Depot_error (qdbm)   Villa (qdbm)   
ADBM (qdbm)   Curia_error (qdbm)   DBM_error (qdbm)   
  V  
Villa_error (qdbm)   
  C  
  D  
Depot (qdbm)   
A | C | D | V
Generated on Thu Aug 5 02:15:30 2010 for QDBM for C++ by  doxygen 1.6.3
qdbm-1.8.78/plus/xapidoc/classqdbm_1_1Villa.html0000644000175000017500000033626311426320062020456 0ustar mikiomikio QDBM for C++: qdbm::Villa Class Reference

qdbm::Villa Class Reference

C++ API of Villa, the basic API of QDBM. More...

Inheritance diagram for qdbm::Villa:
qdbm::ADBM

List of all members.

Public Member Functions

 Villa (const char *name, int omode=Villa::OREADER, VLCFUNC cmp=Villa::cmplex) throw (Villa_error)
 Get the database handle.
virtual ~Villa () throw ()
 Release the resources.
virtual void close () throw (Villa_error)
 Close the database handle.
virtual bool put (const char *kbuf, int ksiz, const char *vbuf, int vsiz, int dmode=Villa::DOVER) throw (Villa_error)
 Store a record.
virtual bool out (const char *kbuf, int ksiz) throw (Villa_error)
 Delete a record.
virtual char * get (const char *kbuf, int ksiz, int *sp=0) throw (Villa_error)
 Retrieve a record.
virtual int vsiz (const char *kbuf, int ksiz) throw (Villa_error)
 Get the size of the value of a record.
virtual int vnum (const char *kbuf, int ksiz) throw (Villa_error)
 Get the number of records corresponding a key.
virtual bool curfirst () throw (Villa_error)
 Move the cursor to the first record.
virtual bool curlast () throw (Villa_error)
 Move the cursor to the last record.
virtual bool curprev () throw (Villa_error)
 Move the cursor to the previous record.
virtual bool curnext () throw (Villa_error)
 Move the cursor to the next record.
virtual bool curjump (const char *kbuf, int ksiz, int jmode=Villa::JFORWARD) throw (Villa_error)
 Move the cursor to a position around a record.
virtual char * curkey (int *sp=0) throw (Villa_error)
 Get the key of the record where the cursor is.
virtual char * curval (int *sp=0) throw (Villa_error)
 Get the value of the record where the cursor is.
virtual bool curput (const char *vbuf, int vsiz, int cpmode=Villa::CPCURRENT) throw (Villa_error)
 Insert a record around the cursor.
virtual bool curout () throw (Villa_error)
 Delete the record where the cursor is.
virtual void settuning (int lrecmax, int nidxmax, int lcnum, int ncnum) throw (Villa_error)
 Set the tuning parameters for performance.
virtual void sync () throw (Villa_error)
 Synchronize updating contents with the file and the device.
virtual void optimize () throw (Villa_error)
 Optimize a database.
virtual char * name () throw (Villa_error)
 Get the name of the database.
virtual int fsiz () throw (Villa_error)
 Get the size of the database file.
virtual int lnum () throw (Villa_error)
 Get the number of the leaf nodes of B+ tree.
virtual int nnum () throw (Villa_error)
 Get the number of the non-leaf nodes of B+ tree.
virtual int rnum () throw (Villa_error)
 Get the number of the records stored in a database.
virtual bool writable () throw (Villa_error)
 Check whether the database handle is a writer or not.
virtual bool fatalerror () throw (Villa_error)
 Check whether the database has a fatal error or not.
virtual int inode () throw (Villa_error)
 Get the inode number of the database file.
virtual time_t mtime () throw (Villa_error)
 Get the last modified time of the database.
virtual void tranbegin () throw (Villa_error)
 Begin the transaction.
virtual void trancommit () throw (Villa_error)
 Commit the transaction.
virtual void tranabort () throw (Villa_error)
 Abort the transaction.
virtual void storerec (const Datum &key, const Datum &val, bool replace=true) throw (Villa_error)
 Store a record.
virtual void deleterec (const Datum &key) throw (Villa_error)
 Delete a record.
virtual Datum fetchrec (const Datum &key) throw (Villa_error)
 Fetch a record.
virtual Datum firstkey () throw (Villa_error)
 Get the first key.
virtual Datum nextkey () throw (Villa_error)
 Get the next key.
virtual bool error () throw (Villa_error)
 Check whether a fatal error occured or not.

Static Public Member Functions

static const char * version () throw ()
 Get the version information.
static void remove (const char *name) throw (Villa_error)
 Remove a database directory.
static int cmplex (const char *aptr, int asiz, const char *bptr, int bsiz) throw ()
 Compare keys of two records by lexical order.
static int cmpint (const char *aptr, int asiz, const char *bptr, int bsiz) throw ()
 Compare keys of two records as integers.
static int cmpnum (const char *aptr, int asiz, const char *bptr, int bsiz) throw ()
 Compare keys of two records as numbers of big endian.
static int cmpdec (const char *aptr, int asiz, const char *bptr, int bsiz) throw ()
 Compare keys of two records as decimal strings.

Public Attributes

bool silent
 whether to repress frequent exceptions

Static Public Attributes

static const int ENOERR
 error code: no error
static const int EFATAL
 error code: with fatal error
static const int EMODE
 error code: invalid mode
static const int EBROKEN
 error code: broken database file
static const int EKEEP
 error code: existing record
static const int ENOITEM
 error code: no item found
static const int EALLOC
 error code: memory allocation error
static const int EMAP
 error code: memory mapping error
static const int EOPEN
 error code: open error
static const int ECLOSE
 error code: close error
static const int ETRUNC
 error code: trunc error
static const int ESYNC
 error code: sync error
static const int ESTAT
 error code: stat error
static const int ESEEK
 error code: seek error
static const int EREAD
 error code: read error
static const int EWRITE
 error code: write error
static const int ELOCK
 error code: lock error
static const int EUNLINK
 error code: unlink error
static const int EMKDIR
 error code: mkdir error
static const int ERMDIR
 error code: rmdir error
static const int EMISC
 error code: miscellaneous error
static const int OREADER
 open mode: open as a reader
static const int OWRITER
 open mode: open as a writer
static const int OCREAT
 open mode: writer creating
static const int OTRUNC
 open mode: writer truncating
static const int ONOLCK
 open mode: open without locking
static const int OLCKNB
 open mode: lock without blocking
static const int OZCOMP
 open mode: compress leaves with ZLIB
static const int OYCOMP
 open mode: compress leaves with LZO
static const int OXCOMP
 open mode: compress leaves with BZIP2
static const int DOVER
 write mode: overwrite the existing value
static const int DKEEP
 write mode: keep the existing value
static const int DCAT
 write mode: concatenate values
static const int DDUP
 write mode: allow duplication of keys
static const int DDUPR
 write mode: allow duplication with reverse order
static const int JFORWARD
 jump mode: step forward
static const int JBACKWARD
 jump mode: step backward
static const int CPCURRENT
 insertion mode: overwrite the current record
static const int CPBEFORE
 insertion mode: insert before the current record
static const int CPAFTER
 insertion mode: insert after the current record

Detailed Description

C++ API of Villa, the basic API of QDBM.


Constructor & Destructor Documentation

qdbm::Villa::Villa ( const char *  name,
int  omode = Villa::OREADER,
VLCFUNC  cmp = Villa::cmplex 
) throw (Villa_error)

Get the database handle.

Parameters:
name the name of a database file.
omode the connection mode: `VillaOWRITER' as a writer, `VillaOREADER' as a reader. If the mode is `VillaOWRITER', the following may be added by bitwise or: `VillaOCREAT', which means it creates a new database if not exist, `VillaOTRUNC', which means it creates a new database regardless if one exists, `VillaOZCOMP', which means leaves in the database are compressed with ZLIB, `VillaOYCOMP', which means leaves in the database are compressed with LZO, `VillaOXCOMP', which means leaves in the database are compressed with BZIP2. Both of `VillaOREADER' and `VillaOWRITER' can be added to by bitwise or: `VillaONOLCK', which means it opens a database file without file locking, or `VillaOLCKNB', which means locking is performed without blocking.
cmp the comparing function: `Villacmplex' comparing keys in lexical order, `Villacmpint' comparing keys as objects of `int' in native byte order, `Villacmpnum' comparing keys as numbers of big endian, `Villacmpdec' comparing keys as decimal strings. Any function compatible with them can be assigned to the comparing function. The comparing function should be kept same in the life of a database.
Exceptions:
Villa_error if an error occurs.
Note:
While connecting as a writer, an exclusive lock is invoked to the database file. While connecting as a reader, a shared lock is invoked to the database file. The thread blocks until the lock is achieved. `VillaOZCOMP', `VillaOYCOMP', and `VillaOXCOMP' are available only if QDBM was built each with ZLIB, LZO, and BZIP2 enabled. If `VillaONOLCK' is used, the application is responsible for exclusion control.
virtual qdbm::Villa::~Villa (  )  throw () [virtual]

Release the resources.

Note:
If the database handle is not closed yet, it is closed.

Member Function Documentation

virtual void qdbm::Villa::close (  )  throw (Villa_error) [virtual]

Close the database handle.

Exceptions:
Villa_error if an error occurs.
Note:
Updating a database is assured to be written when the handle is closed. If a writer opens a database but does not close it appropriately, the database will be broken. If the transaction is activated and not committed, it is aborted.

Implements qdbm::ADBM.

static int qdbm::Villa::cmpdec ( const char *  aptr,
int  asiz,
const char *  bptr,
int  bsiz 
) throw () [static]

Compare keys of two records as decimal strings.

Parameters:
aptr the pointer to the region of one key.
asiz the size of the region of one key.
bptr the pointer to the region of the other key.
bsiz the size of the region of the other key.
Returns:
positive if the former is big, negative if the latter is big, 0 if both are equivalent.
static int qdbm::Villa::cmpint ( const char *  aptr,
int  asiz,
const char *  bptr,
int  bsiz 
) throw () [static]

Compare keys of two records as integers.

Parameters:
aptr the pointer to the region of one key.
asiz the size of the region of one key.
bptr the pointer to the region of the other key.
bsiz the size of the region of the other key.
Returns:
positive if the former is big, negative if the latter is big, 0 if both are equivalent.
static int qdbm::Villa::cmplex ( const char *  aptr,
int  asiz,
const char *  bptr,
int  bsiz 
) throw () [static]

Compare keys of two records by lexical order.

Parameters:
aptr the pointer to the region of one key.
asiz the size of the region of one key.
bptr the pointer to the region of the other key.
bsiz the size of the region of the other key.
Returns:
positive if the former is big, negative if the latter is big, 0 if both are equivalent.
static int qdbm::Villa::cmpnum ( const char *  aptr,
int  asiz,
const char *  bptr,
int  bsiz 
) throw () [static]

Compare keys of two records as numbers of big endian.

Parameters:
aptr the pointer to the region of one key.
asiz the size of the region of one key.
bptr the pointer to the region of the other key.
bsiz the size of the region of the other key.
Returns:
positive if the former is big, negative if the latter is big, 0 if both are equivalent.
virtual bool qdbm::Villa::curfirst (  )  throw (Villa_error) [virtual]

Move the cursor to the first record.

Returns:
always true. However, if the silent flag is true and no record corresponds, false is returned instead of exception.
Exceptions:
Villa_error if an error occurs or there is no record in the database.
virtual bool qdbm::Villa::curjump ( const char *  kbuf,
int  ksiz,
int  jmode = Villa::JFORWARD 
) throw (Villa_error) [virtual]

Move the cursor to a position around a record.

Parameters:
kbuf the pointer to the region of a key.
ksiz the size of the region of the key. If it is negative, the size is assigned with `stdstrlen(kbuf)'.
jmode detail adjustment: `VillaJFORWARD', which means that the cursor is set to the first record of the same key and that the cursor is set to the next substitute if completely matching record does not exist, `VillaJBACKWARD', which means that the cursor is set to the last record of the same key and that the cursor is set to the previous substitute if completely matching record does not exist.
Returns:
always true. However, if the silent flag is true and no record corresponds, false is returned instead of exception.
Exceptions:
Villa_error if an error occurs or there is no record corresponding the condition.
virtual char* qdbm::Villa::curkey ( int *  sp = 0  )  throw (Villa_error) [virtual]

Get the key of the record where the cursor is.

Parameters:
sp the pointer to a variable to which the size of the region of the return value is assigned. If it is 0, it is not used.
Returns:
the pointer to the region of the key of the corresponding record. If the silent flag is true and no record corresponds, 0 is returned instead of exception.
Exceptions:
Villa_error if an error occurs or no record corresponds to the cursor.
Note:
Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `stdmalloc' call, it should be released with the `stdfree' call if it is no longer in use.
virtual bool qdbm::Villa::curlast (  )  throw (Villa_error) [virtual]

Move the cursor to the last record.

Returns:
always true. However, if the silent flag is true and no record corresponds, false is returned instead of exception.
Exceptions:
Villa_error if an error occurs or there is no record in the database.
virtual bool qdbm::Villa::curnext (  )  throw (Villa_error) [virtual]

Move the cursor to the next record.

Returns:
always true. However, if the silent flag is true and no record corresponds, false is returned instead of exception.
Exceptions:
Villa_error if an error occurs or there is no next record.
virtual bool qdbm::Villa::curout (  )  throw (Villa_error) [virtual]

Delete the record where the cursor is.

Returns:
always true. However, if the silent flag is true and no record corresponds to the cursor, false is returned instead of exception.
Exceptions:
Villa_error if an error occurs or no record corresponds to the cursor.
Note:
After deletion, the cursor is moved to the next record if possible.
virtual bool qdbm::Villa::curprev (  )  throw (Villa_error) [virtual]

Move the cursor to the previous record.

Returns:
always true. However, if the silent flag is true and no record corresponds, false is returned instead of exception.
Exceptions:
Villa_error if an error occurs or there is no previous record.
virtual bool qdbm::Villa::curput ( const char *  vbuf,
int  vsiz,
int  cpmode = Villa::CPCURRENT 
) throw (Villa_error) [virtual]

Insert a record around the cursor.

Parameters:
vbuf the pointer to the region of a value.
vsiz the size of the region of the value. If it is negative, the size is assigned with `stdstrlen(vbuf)'.
cpmode detail adjustment: `VillaCPCURRENT', which means that the value of the current record is overwritten, `VillaCPBEFORE', which means that a new record is inserted before the current record, `VillaCPAFTER', which means that a new record is inserted after the current record.
Returns:
always true. However, if the silent flag is true and no record corresponds to the cursor, false is returned instead of exception.
Exceptions:
Villa_error if an error occurs or no record corresponds to the cursor.
Note:
After insertion, the cursor is moved to the inserted record.
virtual char* qdbm::Villa::curval ( int *  sp = 0  )  throw (Villa_error) [virtual]

Get the value of the record where the cursor is.

Parameters:
sp the pointer to a variable to which the size of the region of the return value is assigned. If it is 0, it is not used.
Returns:
the pointer to the region of the value of the corresponding record. If the silent flag is true and no record corresponds, 0 is returned instead of exception.
Exceptions:
Villa_error if an error occurs or no record corresponds to the cursor.
Note:
Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `stdmalloc' call, it should be released with the `stdfree' call if it is no longer in use.
virtual void qdbm::Villa::deleterec ( const Datum key  )  throw (Villa_error) [virtual]

Delete a record.

Parameters:
key reference to a key object.
Exceptions:
Villa_error if an error occurs or no record corresponds.

Implements qdbm::ADBM.

virtual bool qdbm::Villa::error (  )  throw (Villa_error) [virtual]

Check whether a fatal error occured or not.

Returns:
true if the database has a fatal error, false if not.
Exceptions:
Villa_error if an error occurs.

Implements qdbm::ADBM.

virtual bool qdbm::Villa::fatalerror (  )  throw (Villa_error) [virtual]

Check whether the database has a fatal error or not.

Returns:
true if the database has a fatal error, false if not.
Exceptions:
Villa_error if an error occurs.
virtual Datum qdbm::Villa::fetchrec ( const Datum key  )  throw (Villa_error) [virtual]

Fetch a record.

Parameters:
key reference to a key object.
Returns:
a temporary instance of the value of the corresponding record.
Exceptions:
Villa_error if an error occurs or no record corresponds.

Implements qdbm::ADBM.

virtual Datum qdbm::Villa::firstkey (  )  throw (Villa_error) [virtual]

Get the first key.

Returns:
a temporary instance of the key of the first record.
Exceptions:
Villa_error if an error occurs or no record corresponds.

Implements qdbm::ADBM.

virtual int qdbm::Villa::fsiz (  )  throw (Villa_error) [virtual]

Get the size of the database file.

Returns:
the size of the database file.
Exceptions:
Villa_error if an error occurs.
Note:
Because of the I/O buffer, the return value may be less than the real size.
virtual char* qdbm::Villa::get ( const char *  kbuf,
int  ksiz,
int *  sp = 0 
) throw (Villa_error) [virtual]

Retrieve a record.

Parameters:
kbuf the pointer to the region of a key.
ksiz the size of the region of the key. If it is negative, the size is assigned with `stdstrlen(kbuf)'.
sp the pointer to a variable to which the size of the region of the return value is assigned. If it is 0, it is not used.
Returns:
the pointer to the region of the value of the corresponding record. If the silent flag is true and no record corresponds, 0 is returned instead of exception.
Exceptions:
Villa_error if an error occurs or no record corresponds.
Note:
When the key of duplicated records is specified, the value of the first record of the same key is selected. Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `stdmalloc' call, it should be released with the `stdfree' call if it is no longer in use.
virtual int qdbm::Villa::inode (  )  throw (Villa_error) [virtual]

Get the inode number of the database file.

Returns:
the inode number of the database file.
Exceptions:
Villa_error if an error occurs.
virtual int qdbm::Villa::lnum (  )  throw (Villa_error) [virtual]

Get the number of the leaf nodes of B+ tree.

Returns:
the number of the leaf nodes.
Exceptions:
Villa_error if an error occurs.
virtual time_t qdbm::Villa::mtime (  )  throw (Villa_error) [virtual]

Get the last modified time of the database.

Returns:
the last modified time the database.
Exceptions:
Villa_error if an error occurs.
virtual char* qdbm::Villa::name (  )  throw (Villa_error) [virtual]

Get the name of the database.

Returns:
the pointer to the region of the name of the database.
Exceptions:
Villa_error if an error occurs.
Note:
Because the region of the return value is allocated with the `stdmalloc' call, it should be released with the `stdfree' call if it is no longer in use.
virtual Datum qdbm::Villa::nextkey (  )  throw (Villa_error) [virtual]

Get the next key.

Returns:
a temporary instance of the key of the next record.
Exceptions:
Villa_error if an error occurs or no record corresponds.

Implements qdbm::ADBM.

virtual int qdbm::Villa::nnum (  )  throw (Villa_error) [virtual]

Get the number of the non-leaf nodes of B+ tree.

Returns:
the number of the non-leaf nodes.
Exceptions:
Villa_error if an error occurs.
virtual void qdbm::Villa::optimize (  )  throw (Villa_error) [virtual]

Optimize a database.

Exceptions:
Villa_error if an error occurs.
Note:
In an alternating succession of deleting and storing with overwrite or concatenate, dispensable regions accumulate. This function is useful to do away with them. This function shuold not be used while the transaction is activated.
virtual bool qdbm::Villa::out ( const char *  kbuf,
int  ksiz 
) throw (Villa_error) [virtual]

Delete a record.

Parameters:
kbuf the pointer to the region of a key.
ksiz the size of the region of the key. If it is negative, the size is assigned with `stdstrlen(kbuf)'.
Returns:
always true. However, if the silent flag is true and no record corresponds, false is returned instead of exception.
Exceptions:
Villa_error if an error occurs or no record corresponds.
Note:
When the key of duplicated records is specified, the first record of the same key is deleted. The cursor becomes unavailable due to updating database.
virtual bool qdbm::Villa::put ( const char *  kbuf,
int  ksiz,
const char *  vbuf,
int  vsiz,
int  dmode = Villa::DOVER 
) throw (Villa_error) [virtual]

Store a record.

Parameters:
kbuf the pointer to the region of a key.
ksiz the size of the region of the key. If it is negative, the size is assigned with `stdstrlen(kbuf)'.
vbuf the pointer to the region of a value.
vsiz the size of the region of the value. If it is negative, the size is assigned with `stdstrlen(vbuf)'.
dmode behavior when the key overlaps, by the following values: `VillaDOVER', which means the specified value overwrites the existing one, `VillaDKEEP', which means the existing value is kept, `VillaDCAT', which means the specified value is concatenated at the end of the existing value, `VillaDDUP', which means duplication of keys is allowed and the specified value is added as the last one, `VillaDDUPR', which means duplication of keys is allowed and the specified value is added as the first one.
Returns:
always true. However, if the silent flag is true and replace is cancelled, false is returned instead of exception.
Exceptions:
Villa_error if an error occurs or replace is cancelled.
Note:
The cursor becomes unavailable due to updating database.
static void qdbm::Villa::remove ( const char *  name  )  throw (Villa_error) [static]

Remove a database directory.

Parameters:
name the name of a database directory.
Exceptions:
Villa_error if an error occurs.
virtual int qdbm::Villa::rnum (  )  throw (Villa_error) [virtual]

Get the number of the records stored in a database.

Returns:
the number of the records stored in the database.
Exceptions:
Villa_error if an error occurs.
virtual void qdbm::Villa::settuning ( int  lrecmax,
int  nidxmax,
int  lcnum,
int  ncnum 
) throw (Villa_error) [virtual]

Set the tuning parameters for performance.

Parameters:
lrecmax the max number of records in a leaf node of B+ tree. If it is not more than 0, the default value is specified.
nidxmax the max number of indexes in a non-leaf node of B+ tree. If it is not more than 0, the default value is specified.
lcnum the max number of caching leaf nodes. If it is not more than 0, the default value is specified.
ncnum the max number of caching non-leaf nodes. If it is not more than 0, the default value is specified.
Exceptions:
Villa_error if an error occurs.
Note:
The default setting is equivalent to `settuning(49, 192, 1024, 512)'. Because tuning paremeters are not saved in a database, you should specify them every opening a database.
virtual void qdbm::Villa::storerec ( const Datum key,
const Datum val,
bool  replace = true 
) throw (Villa_error) [virtual]

Store a record.

Parameters:
key reference to a key object.
val reference to a value object.
replace whether the existing value is to be overwritten or not.
Exceptions:
Villa_error if an error occurs or replace is cancelled.

Implements qdbm::ADBM.

virtual void qdbm::Villa::sync (  )  throw (Villa_error) [virtual]

Synchronize updating contents with the file and the device.

Exceptions:
Villa_error if an error occurs.
Note:
This function is useful when another process uses the connected database file. This function shuold not be used while the transaction is activated.
virtual void qdbm::Villa::tranabort (  )  throw (Villa_error) [virtual]

Abort the transaction.

Exceptions:
Villa_error if an error occurs.
Note:
Updating a database in the transaction is discarded when it is aborted. The state of the database is rollbacked to before transaction. Any other thread except for the one which began the transaction should not call this function.
virtual void qdbm::Villa::tranbegin (  )  throw (Villa_error) [virtual]

Begin the transaction.

Exceptions:
Villa_error if an error occurs.
Note:
If a thread is already in the transaction, the other threads block until the prius is out of the transaction. Only one transaction can be activated with a database handle at the same time.
virtual void qdbm::Villa::trancommit (  )  throw (Villa_error) [virtual]

Commit the transaction.

Exceptions:
Villa_error if an error occurs.
Note:
Updating a database in the transaction is fixed when it is committed successfully. Any other thread except for the one which began the transaction should not call this function.
static const char* qdbm::Villa::version (  )  throw () [static]

Get the version information.

Returns:
the string of the version information.
virtual int qdbm::Villa::vnum ( const char *  kbuf,
int  ksiz 
) throw (Villa_error) [virtual]

Get the number of records corresponding a key.

Parameters:
kbuf the pointer to the region of a key.
ksiz the size of the region of the key. If it is negative, the size is assigned with `stdstrlen(kbuf)'.
Returns:
the number of corresponding records. If no record corresponds, 0 is returned.
Exceptions:
Villa_error if an error occurs.
virtual int qdbm::Villa::vsiz ( const char *  kbuf,
int  ksiz 
) throw (Villa_error) [virtual]

Get the size of the value of a record.

Parameters:
kbuf the pointer to the region of a key.
ksiz the size of the region of the key. If it is negative, the size is assigned with `stdstrlen(kbuf)'.
Returns:
the size of the value of the corresponding record. If the silent flag is true and no record corresponds, -1 is returned instead of exception. If multiple records correspond, the size of the first is returned.
Exceptions:
Villa_error if an error occurs or no record corresponds.
virtual bool qdbm::Villa::writable (  )  throw (Villa_error) [virtual]

Check whether the database handle is a writer or not.

Returns:
true if the handle is a writer, false if not.
Exceptions:
Villa_error if an error occurs.

The documentation for this class was generated from the following file:
  • xvilla.h
Generated on Thu Aug 5 02:15:30 2010 for QDBM for C++ by  doxygen 1.6.3
qdbm-1.8.78/plus/xapidoc/classqdbm_1_1Depot.html0000644000175000017500000025142011426320062020451 0ustar mikiomikio QDBM for C++: qdbm::Depot Class Reference

qdbm::Depot Class Reference

C++ API of Depot, the basic API of QDBM. More...

Inheritance diagram for qdbm::Depot:
qdbm::ADBM

List of all members.

Public Member Functions

 Depot (const char *name, int omode=Depot::OREADER, int bnum=-1) throw (Depot_error)
 Get the database handle.
virtual ~Depot () throw ()
 Release the resources.
virtual void close () throw (Depot_error)
 Close the database handle.
virtual bool put (const char *kbuf, int ksiz, const char *vbuf, int vsiz, int dmode=Depot::DOVER) throw (Depot_error)
 Store a record.
virtual bool out (const char *kbuf, int ksiz) throw (Depot_error)
 Delete a record.
virtual char * get (const char *kbuf, int ksiz, int start=0, int max=-1, int *sp=0) throw (Depot_error)
 Retrieve a record.
virtual int getwb (const char *kbuf, int ksiz, int start, int max, char *vbuf) throw (Depot_error)
 Retrieve a record and write the value into a buffer.
virtual int vsiz (const char *kbuf, int ksiz) throw (Depot_error)
 Get the size of the value of a record.
virtual void iterinit () throw (Depot_error)
 Initialize the iterator of the database handle.
virtual char * iternext (int *sp=0) throw (Depot_error)
 Get the next key of the iterator.
virtual void setalign (int align) throw (Depot_error)
 Set alignment of the database handle.
virtual void setfbpsiz (int size) throw (Depot_error)
 Set the size of the free block pool.
virtual void sync () throw (Depot_error)
 Synchronize updating contents with the file and the device.
virtual void optimize (int bnum=-1) throw (Depot_error)
 Optimize the database.
virtual char * name () throw (Depot_error)
 Get the name of the database.
virtual int fsiz () throw (Depot_error)
 Get the size of the database file.
virtual int bnum () throw (Depot_error)
 Get the number of the elements of the bucket array.
virtual int busenum () throw (Depot_error)
 Get the number of the used elements of the bucket array.
virtual int rnum () throw (Depot_error)
 Get the number of the records stored in the database.
virtual bool writable () throw (Depot_error)
 Check whether the database handle is a writer or not.
virtual bool fatalerror () throw (Depot_error)
 Check whether the database has a fatal error or not.
virtual int inode () throw (Depot_error)
 Get the inode number of the database file.
virtual time_t mtime () throw (Depot_error)
 Get the last modified time of the database.
virtual int fdesc () throw (Depot_error)
 Get the file descriptor of the database file.
virtual void storerec (const Datum &key, const Datum &val, bool replace=true) throw (Depot_error)
 Store a record.
virtual void deleterec (const Datum &key) throw (Depot_error)
 Delete a record.
virtual Datum fetchrec (const Datum &key) throw (Depot_error)
 Fetch a record.
virtual Datum firstkey () throw (Depot_error)
 Get the first key.
virtual Datum nextkey () throw (Depot_error)
 Get the next key.
virtual bool error () throw (Depot_error)
 Check whether a fatal error occured or not.

Static Public Member Functions

static const char * version () throw ()
 Get the version information.
static void remove (const char *name) throw (Depot_error)
 Remove a database file.
static char * snaffle (const char *name, const char *kbuf, int ksiz, int *sp) throw (Depot_error)
 Retrieve a record directly from a database file.

Public Attributes

bool silent
 whether to repress frequent exceptions

Static Public Attributes

static const int ENOERR
 error code: no error
static const int EFATAL
 error code: with fatal error
static const int EMODE
 error code: invalid mode
static const int EBROKEN
 error code: broken database file
static const int EKEEP
 error code: existing record
static const int ENOITEM
 error code: no item found
static const int EALLOC
 error code: memory allocation error
static const int EMAP
 error code: memory mapping error
static const int EOPEN
 error code: open error
static const int ECLOSE
 error code: close error
static const int ETRUNC
 error code: trunc error
static const int ESYNC
 error code: sync error
static const int ESTAT
 error code: stat error
static const int ESEEK
 error code: seek error
static const int EREAD
 error code: read error
static const int EWRITE
 error code: write error
static const int ELOCK
 error code: lock error
static const int EUNLINK
 error code: unlink error
static const int EMKDIR
 error code: mkdir error
static const int ERMDIR
 error code: rmdir error
static const int EMISC
 error code: miscellaneous error
static const int OREADER
 open mode: open as a reader
static const int OWRITER
 open mode: open as a writer
static const int OCREAT
 open mode: writer creating
static const int OTRUNC
 open mode: writer truncating
static const int ONOLCK
 open mode: open without locking
static const int OLCKNB
 open mode: lock without blocking
static const int OSPARSE
 open mode: create as a sparse file
static const int DOVER
 write mode: overwrite the existing value
static const int DKEEP
 write mode: keep the existing value
static const int DCAT
 write mode: concatenate values

Detailed Description

C++ API of Depot, the basic API of QDBM.


Constructor & Destructor Documentation

qdbm::Depot::Depot ( const char *  name,
int  omode = Depot::OREADER,
int  bnum = -1 
) throw (Depot_error)

Get the database handle.

Parameters:
name the name of a database file.
omode the connection mode: `DepotOWRITER' as a writer, `DepotOREADER' as a reader. If the mode is `DepotOWRITER', the following may be added by bitwise or: `DepotOCREAT', which means it creates a new database if not exist, `DepotOTRUNC', which means it creates a new database regardless if one exists. Both of `DepotOREADER' and `DepotOWRITER' can be added to by bitwise or: `DepotONOLCK', which means it opens a database file without file locking, or `DepotOLCKNB', which means locking is performed without blocking. `DepotOCREAT' can be added to by bitwise or: `DepotOSPARSE', which means it creates a database file as a sparse file.
bnum the number of elements of the bucket array. If it is not more than 0, the default value is specified. The size of a bucket array is determined on creating, and can not be changed except for by optimization of the database. Suggested size of a bucket array is about from 0.5 to 4 times of the number of all records to store.
Exceptions:
Depot_error if an error occurs.
Note:
While connecting as a writer, an exclusive lock is invoked to the database file. While connecting as a reader, a shared lock is invoked to the database file. The thread blocks until the lock is achieved. If `DepotONOLCK' is used, the application is responsible for exclusion control.
virtual qdbm::Depot::~Depot (  )  throw () [virtual]

Release the resources.

Note:
If the database handle is not closed yet, it is closed.

Member Function Documentation

virtual int qdbm::Depot::bnum (  )  throw (Depot_error) [virtual]

Get the number of the elements of the bucket array.

Returns:
the number of the elements of the bucket array.
Exceptions:
Depot_error if an error occurs.
virtual int qdbm::Depot::busenum (  )  throw (Depot_error) [virtual]

Get the number of the used elements of the bucket array.

Returns:
the number of the used elements of the bucket array.
Exceptions:
Depot_error if an error occurs.
Note:
This function is inefficient because it accesses all elements of the bucket array.
virtual void qdbm::Depot::close (  )  throw (Depot_error) [virtual]

Close the database handle.

Exceptions:
Depot_error if an error occurs.
Note:
Updating a database is assured to be written when the handle is closed. If a writer opens a database but does not close it appropriately, the database will be broken.

Implements qdbm::ADBM.

virtual void qdbm::Depot::deleterec ( const Datum key  )  throw (Depot_error) [virtual]

Delete a record.

Parameters:
key reference to a key object.
Exceptions:
Depot_error if an error occurs or no record corresponds.

Implements qdbm::ADBM.

virtual bool qdbm::Depot::error (  )  throw (Depot_error) [virtual]

Check whether a fatal error occured or not.

Returns:
true if the database has a fatal error, false if not.
Exceptions:
Depot_error if an error occurs.

Implements qdbm::ADBM.

virtual bool qdbm::Depot::fatalerror (  )  throw (Depot_error) [virtual]

Check whether the database has a fatal error or not.

Returns:
true if the database has a fatal error, false if not.
Exceptions:
Depot_error if an error occurs.
virtual int qdbm::Depot::fdesc (  )  throw (Depot_error) [virtual]

Get the file descriptor of the database file.

Returns:
the file descriptor of the database file.
Exceptions:
Depot_error if an error occurs.
Note:
Handling the file descriptor of a database file directly is not suggested.
virtual Datum qdbm::Depot::fetchrec ( const Datum key  )  throw (Depot_error) [virtual]

Fetch a record.

Parameters:
key reference to a key object.
Returns:
a temporary instance of the value of the corresponding record.
Exceptions:
Depot_error if an error occurs or no record corresponds.

Implements qdbm::ADBM.

virtual Datum qdbm::Depot::firstkey (  )  throw (Depot_error) [virtual]

Get the first key.

Returns:
a temporary instance of the key of the first record.
Exceptions:
Depot_error if an error occurs or no record corresponds.

Implements qdbm::ADBM.

virtual int qdbm::Depot::fsiz (  )  throw (Depot_error) [virtual]

Get the size of the database file.

Returns:
the size of the database file.
Exceptions:
Depot_error if an error occurs.
virtual char* qdbm::Depot::get ( const char *  kbuf,
int  ksiz,
int  start = 0,
int  max = -1,
int *  sp = 0 
) throw (Depot_error) [virtual]

Retrieve a record.

Parameters:
kbuf the pointer to the region of a key.
ksiz the size of the region of the key. If it is negative, the size is assigned with `stdstrlen(kbuf)'.
start the offset address of the beginning of the region of the value to be read.
max the max size to read with. If it is negative, the size is unlimited.
sp the pointer to a variable to which the size of the region of the return value is assigned. If it is 0, it is not used.
Returns:
the pointer to the region of the value of the corresponding record. If the silent flag is true and no record corresponds, 0 is returned instead of exception.
Exceptions:
Depot_error if an error occurs, no record corresponds, or the size of the value of the corresponding record is less than `start'.
Note:
Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `stdmalloc' call, it should be released with the `stdfree' call if it is no longer in use.
virtual int qdbm::Depot::getwb ( const char *  kbuf,
int  ksiz,
int  start,
int  max,
char *  vbuf 
) throw (Depot_error) [virtual]

Retrieve a record and write the value into a buffer.

Parameters:
kbuf the pointer to the region of a key.
ksiz the size of the region of the key. If it is negative, the size is assigned with `stdstrlen(kbuf)'.
start the offset address of the beginning of the region of the value to be read.
max the max size to be read. It shuld be equal to or less than the size of the writing buffer.
vbuf the pointer to a buffer into which the value of the corresponding record is written.
Returns:
the return value is the size of the written data. If the silent flag is true and no record corresponds, -1 is returned instead of exception.
Exceptions:
Depot_error if an error occurs, no record corresponds, or the size of the value of the corresponding record is less than `start'.
Note:
No additional zero code is appended at the end of the region of the writing buffer.
virtual int qdbm::Depot::inode (  )  throw (Depot_error) [virtual]

Get the inode number of the database file.

Returns:
the inode number of the database file.
Exceptions:
Depot_error if an error occurs.
virtual void qdbm::Depot::iterinit (  )  throw (Depot_error) [virtual]

Initialize the iterator of the database handle.

Exceptions:
Depot_error if an error occurs.
Note:
The iterator is used in order to access the key of every record stored in a database.
virtual char* qdbm::Depot::iternext ( int *  sp = 0  )  throw (Depot_error) [virtual]

Get the next key of the iterator.

Parameters:
sp the pointer to a variable to which the size of the region of the return value is assigned. If it is 0, it is not used.
Returns:
the pointer to the region of the next key. If the silent flag is true and no record corresponds, 0 is returned instead of exception.
Exceptions:
Depot_error if an error occurs or no record is to be get out of the iterator.
Note:
Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `stdmalloc' call, it should be released with the `stdfree' call if it is no longer in use. It is possible to access every record by iteration of calling this function. However, it is not assured if updating the database is occurred while the iteration. Besides, the order of this traversal access method is arbitrary, so it is not assured that the order of storing matches the one of the traversal access.
virtual time_t qdbm::Depot::mtime (  )  throw (Depot_error) [virtual]

Get the last modified time of the database.

Returns:
the last modified time the database.
Exceptions:
Depot_error if an error occurs.
virtual char* qdbm::Depot::name (  )  throw (Depot_error) [virtual]

Get the name of the database.

Returns:
the pointer to the region of the name of the database.
Exceptions:
Depot_error if an error occurs.
Note:
Because the region of the return value is allocated with the `stdmalloc' call, it should be released with the `stdfree' call if it is no longer in use.
virtual Datum qdbm::Depot::nextkey (  )  throw (Depot_error) [virtual]

Get the next key.

Returns:
a temporary instance of the key of the next record.
Exceptions:
Depot_error if an error occurs or no record corresponds.

Implements qdbm::ADBM.

virtual void qdbm::Depot::optimize ( int  bnum = -1  )  throw (Depot_error) [virtual]

Optimize the database.

Parameters:
bnum the number of the elements of the bucket array. If it is not more than 0, the default value is specified.
Exceptions:
Depot_error if an error occurs.
Note:
In an alternating succession of deleting and storing with overwrite or concatenate, dispensable regions accumulate. This function is useful to do away with them.
virtual bool qdbm::Depot::out ( const char *  kbuf,
int  ksiz 
) throw (Depot_error) [virtual]

Delete a record.

Parameters:
kbuf the pointer to the region of a key.
ksiz the size of the region of the key. If it is negative, the size is assigned with `stdstrlen(kbuf)'.
Returns:
always true. However, if the silent flag is true and no record corresponds, false is returned instead of exception.
Exceptions:
Depot_error if an error occurs or no record corresponds.
virtual bool qdbm::Depot::put ( const char *  kbuf,
int  ksiz,
const char *  vbuf,
int  vsiz,
int  dmode = Depot::DOVER 
) throw (Depot_error) [virtual]

Store a record.

Parameters:
kbuf the pointer to the region of a key.
ksiz the size of the region of the key. If it is negative, the size is assigned with `stdstrlen(kbuf)'.
vbuf the pointer to the region of a value.
vsiz the size of the region of the value. If it is negative, the size is assigned with `stdstrlen(vbuf)'.
dmode behavior when the key overlaps, by the following values: `DepotDOVER', which means the specified value overwrites the existing one, `DepotDKEEP', which means the existing value is kept, `DepotDCAT', which means the specified value is concatenated at the end of the existing value.
Returns:
always true. However, if the silent flag is true and replace is cancelled, false is returned instead of exception.
Exceptions:
Depot_error if an error occurs or replace is cancelled.
static void qdbm::Depot::remove ( const char *  name  )  throw (Depot_error) [static]

Remove a database file.

Parameters:
name the name of a database file.
Exceptions:
Depot_error if an error occurs.
virtual int qdbm::Depot::rnum (  )  throw (Depot_error) [virtual]

Get the number of the records stored in the database.

Returns:
the number of the records stored in the database.
Exceptions:
Depot_error if an error occurs.
virtual void qdbm::Depot::setalign ( int  align  )  throw (Depot_error) [virtual]

Set alignment of the database handle.

Parameters:
align the basic size of alignment.
Exceptions:
Depot_error if an error occurs.
Note:
If alignment is set to a database, the efficiency of overwriting values is improved. The size of alignment is suggested to be average size of the values of the records to be stored. If alignment is positive, padding whose size is multiple number of the alignment is placed. If alignment is negative, as `vsiz' is the size of a value, the size of padding is calculated with `(vsiz / pow(2, abs(align) - 1))'. Because alignment setting is not saved in a database, you should specify alignment every opening a database.
virtual void qdbm::Depot::setfbpsiz ( int  size  )  throw (Depot_error) [virtual]

Set the size of the free block pool.

Parameters:
size the size of the free block pool of a database.
Exceptions:
Depot_error if an error occurs.
Note:
The default size of the free block pool is 16. If the size is greater, the space efficiency of overwriting values is improved with the time efficiency sacrificed.
static char* qdbm::Depot::snaffle ( const char *  name,
const char *  kbuf,
int  ksiz,
int *  sp 
) throw (Depot_error) [static]

Retrieve a record directly from a database file.

Parameters:
name the name of a database file.
kbuf the pointer to the region of a key.
ksiz the size of the region of the key. If it is negative, the size is assigned with `stdstrlen(kbuf)'.
sp the pointer to a variable to which the size of the region of the return value is assigned. If it is 0, it is not used.
Returns:
the pointer to the region of the value of the corresponding record.
Exceptions:
Depot_error if an error occurs or no record corresponds.
Note:
Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `stdmalloc' call, it should be released with the `stdfree' call if it is no longer in use. Although this method can be used even while the database file is locked by another process, it is not assured that recent updated is reflected.
virtual void qdbm::Depot::storerec ( const Datum key,
const Datum val,
bool  replace = true 
) throw (Depot_error) [virtual]

Store a record.

Parameters:
key reference to a key object.
val reference to a value object.
replace whether the existing value is to be overwritten or not.
Exceptions:
Depot_error if an error occurs or replace is cancelled.

Implements qdbm::ADBM.

virtual void qdbm::Depot::sync (  )  throw (Depot_error) [virtual]

Synchronize updating contents with the file and the device.

Exceptions:
Depot_error if an error occurs.
Note:
This function is useful when another process uses the connected database file.
static const char* qdbm::Depot::version (  )  throw () [static]

Get the version information.

Returns:
the string of the version information.
virtual int qdbm::Depot::vsiz ( const char *  kbuf,
int  ksiz 
) throw (Depot_error) [virtual]

Get the size of the value of a record.

Parameters:
kbuf the pointer to the region of a key.
ksiz the size of the region of the key. If it is negative, the size is assigned with `stdstrlen(kbuf)'.
Returns:
the size of the value of the corresponding record. If the silent flag is true and no record corresponds, -1 is returned instead of exception.
Exceptions:
Depot_error if an error occurs or no record corresponds.
Note:
Because this function does not read the entity of a record, it is faster than `get'.
virtual bool qdbm::Depot::writable (  )  throw (Depot_error) [virtual]

Check whether the database handle is a writer or not.

Returns:
true if the handle is a writer, false if not.
Exceptions:
Depot_error if an error occurs.

The documentation for this class was generated from the following file:
  • xdepot.h
Generated on Thu Aug 5 02:15:30 2010 for QDBM for C++ by  doxygen 1.6.3
qdbm-1.8.78/plus/xapidoc/namespaceqdbm.html0000644000175000017500000003037311426320062017646 0ustar mikiomikio QDBM for C++: qdbm Namespace Reference

qdbm Namespace Reference

Namespace of QDBM. More...

Classes

class  DBM_error
 Error container for ADBM. More...
class  Datum
 Datum of records for ADBM. More...
class  ADBM
 Aabstraction for database managers compatible with DBM. More...
class  Curia_error
 Error container for Curia. More...
class  Curia
 C++ API of Curia, the extended API of QDBM. More...
class  Depot_error
 Error container for Depot. More...
class  Depot
 C++ API of Depot, the basic API of QDBM. More...
class  Villa_error
 Error container for Villa. More...
class  Villa
 C++ API of Villa, the basic API of QDBM. More...

Functions

Datum operator+ (const Datum &former, const Datum &latter)
 Temporary concatenation operator for Datum.
Datum operator+ (const Datum &datum, const char *str)
 Temporary concatenation operator for Datum.
Datum operator+ (const char *str, const Datum &datum)
 Temporary concatenation operator for Datum.

Variables

pthread_mutex_t ourmutex
 Common Mutex of QDBM.

Detailed Description

Namespace of QDBM.


Function Documentation

qdbm::Datum qdbm::operator+ ( const char *  str,
const Datum &  datum 
)

Temporary concatenation operator for Datum.

Parameters:
str the former string.
datum the latter datum.
Returns:
reference to a temporary instance.
qdbm::Datum qdbm::operator+ ( const Datum &  datum,
const char *  str 
)

Temporary concatenation operator for Datum.

Parameters:
datum the former datum.
str the latter string.
Returns:
reference to a temporary instance.
qdbm::Datum qdbm::operator+ ( const Datum &  former,
const Datum &  latter 
)

Temporary concatenation operator for Datum.

Parameters:
former the former datum.
latter the latter datum.
Returns:
reference to a temporary instance.
Generated on Thu Aug 5 02:15:30 2010 for QDBM for C++ by  doxygen 1.6.3
qdbm-1.8.78/plus/xapidoc/doxygen.png0000644000175000017500000000240111426320062016332 0ustar mikiomikio‰PNG  IHDRd-ok>ÂgAMAÖØÔOX2tEXtSoftwareAdobe ImageReadyqÉe<]PLTEǾÏ"&©ÈÎï¶»ÖÓÚú“¢Þ ¬à¶Âõ‡§ÕÙêÉÊÎáâæ{ŽÔ¡ëˆ™× ²ø§¬¹ÀÀ±ÝÝÎùùéõõçëëåED9×ÖËhg]_X<@:#mhUÿÿÿÝÀ1tRNSÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÍvÿIDATxÚbC£: d#„„………h` @¡X",***LKˆ.–], ºX@t± €èb @ÑÅ€BµD„6–š%""´° € ˜% ˆ™B:H¢ˆ²Áf@• ˆRPy"K`\PbC(!II!h©…ëƒ(ñ„Ä!ꈬC„Ä…àl!0[X\J\$TMˆ(’>a$S„ Ù@ Ш@R.$‚¬LJBR¢‰AÌG1 ¬ Â(FȃÔPhhÁTÀ¢„%!`€&q°%u P ¹¢ ¬ € ¹CT$B¢à|‚ºW„¤Àl £!B`R$( …Ĉ‘’ž@AÅ%ĤÄ%@,(—ʂڱ%$ÁââRPmB U`1IˆYB  99€\1 yCCCÿf"[N 'Ü=TGÈ’øl8˜^Kû5<êSæRɤ”%î@@ à›Ê b1 qÅAXHˆ¸&ØB’R y n˜P„Ìã–4A €€j¹€€>Ü ˜ t!˜+(.ÈÅWQ±A2ÜÜMUÜ‚’’‚‚â `1 %`19€F< 3cZÄ`óe!\ˆ DÈ+. 83‹³Àä¸!lYYA -6‚EJŠ¢V €@©žXXX 4„å Ê@86Ð`RdB´€4I "Ý "–@xrÊŒ‚H€AÊ`—f ÉȰCŒ"XV0ɲ³C b@2…¬H ¬È“ p)!(ì‚ 0Ž4ˆ)(%RÁÎ ¶$€TÊ€¥Àþb‡b,säÐ@7À üѰ‚Òî?f¥Ö—\PIx!I´¦"”Ȉ’3¨ QY˜ÿt^^ÛØgv- }>WJOAV`$&#”¦8ùøø8€\FF ›SFJ$ÂÆ€ÐƊС䈉ÀÀ 4ª…Èäå -Á§‡ €H²…—ŸŸŸf ?ðâ5„ €k1Âd‰,ŒÃ ³ƒ“€.€"­F™ËË€àñ‚½ÁIÈ€"±Ù4ÉH gx|‚f©m)))9´. aMDƒ& ºX@t± €èb @ÑÅ€¢‹%DKˆ.–], ºX@t± €èb @€d`‚ɽSµOIEND®B`‚qdbm-1.8.78/plus/xapidoc/classqdbm_1_1DBM__error-members.html0000644000175000017500000000530611426320062023000 0ustar mikiomikio QDBM for C++: Member List

qdbm::DBM_error Member List

This is the complete list of members for qdbm::DBM_error, including all inherited members.
DBM_error()qdbm::DBM_error
DBM_error(const char *message)qdbm::DBM_error
message() const qdbm::DBM_error [virtual]
operator const char *() const qdbm::DBM_error [virtual]
~DBM_error()qdbm::DBM_error [virtual]
Generated on Thu Aug 5 02:15:30 2010 for QDBM for C++ by  doxygen 1.6.3
qdbm-1.8.78/plus/xapidoc/functions_0x64.html0000644000175000017500000001221211426320062017627 0ustar mikiomikio QDBM for C++: Class Members
Here is a list of all documented class members with links to the class documentation for each member:

- d -

Generated on Thu Aug 5 02:15:30 2010 for QDBM for C++ by  doxygen 1.6.3
qdbm-1.8.78/plus/xapidoc/ftv2mlastnode.png0000644000175000017500000000024011426320062017444 0ustar mikiomikio‰PNG  IHDRÃÃÄy PLTEÿÿÿ€€€<^»,tRNS@æØftEXtSoftwaregif2png 2.4.2£^G#IDATxÚc`   `„Œ¡¡ ɨµPʉamºÀÜiÈIEND®B`‚qdbm-1.8.78/plus/xapidoc/functions_0x63.html0000644000175000017500000001367311426320062017642 0ustar mikiomikio QDBM for C++: Class Members
Here is a list of all documented class members with links to the class documentation for each member:

- c -

Generated on Thu Aug 5 02:15:30 2010 for QDBM for C++ by  doxygen 1.6.3
qdbm-1.8.78/plus/xapidoc/namespacemembers_vars.html0000644000175000017500000000324611426320062021407 0ustar mikiomikio QDBM for C++: Class Members
 
Generated on Thu Aug 5 02:15:30 2010 for QDBM for C++ by  doxygen 1.6.3
qdbm-1.8.78/plus/xapidoc/classqdbm_1_1Villa-members.html0000644000175000017500000005245611426320062022105 0ustar mikiomikio QDBM for C++: Member List

qdbm::Villa Member List

This is the complete list of members for qdbm::Villa, including all inherited members.
close()qdbm::Villa [virtual]
cmpdec(const char *aptr, int asiz, const char *bptr, int bsiz)qdbm::Villa [static]
cmpint(const char *aptr, int asiz, const char *bptr, int bsiz)qdbm::Villa [static]
cmplex(const char *aptr, int asiz, const char *bptr, int bsiz)qdbm::Villa [static]
cmpnum(const char *aptr, int asiz, const char *bptr, int bsiz)qdbm::Villa [static]
CPAFTERqdbm::Villa [static]
CPBEFOREqdbm::Villa [static]
CPCURRENTqdbm::Villa [static]
curfirst()qdbm::Villa [virtual]
curjump(const char *kbuf, int ksiz, int jmode=Villa::JFORWARD)qdbm::Villa [virtual]
curkey(int *sp=0)qdbm::Villa [virtual]
curlast()qdbm::Villa [virtual]
curnext()qdbm::Villa [virtual]
curout()qdbm::Villa [virtual]
curprev()qdbm::Villa [virtual]
curput(const char *vbuf, int vsiz, int cpmode=Villa::CPCURRENT)qdbm::Villa [virtual]
curval(int *sp=0)qdbm::Villa [virtual]
DCATqdbm::Villa [static]
DDUPqdbm::Villa [static]
DDUPRqdbm::Villa [static]
deleterec(const Datum &key)qdbm::Villa [virtual]
DKEEPqdbm::Villa [static]
DOVERqdbm::Villa [static]
EALLOCqdbm::Villa [static]
EBROKENqdbm::Villa [static]
ECLOSEqdbm::Villa [static]
EFATALqdbm::Villa [static]
EKEEPqdbm::Villa [static]
ELOCKqdbm::Villa [static]
EMAPqdbm::Villa [static]
EMISCqdbm::Villa [static]
EMKDIRqdbm::Villa [static]
EMODEqdbm::Villa [static]
ENOERRqdbm::Villa [static]
ENOITEMqdbm::Villa [static]
EOPENqdbm::Villa [static]
EREADqdbm::Villa [static]
ERMDIRqdbm::Villa [static]
error()qdbm::Villa [virtual]
ESEEKqdbm::Villa [static]
ESTATqdbm::Villa [static]
ESYNCqdbm::Villa [static]
ETRUNCqdbm::Villa [static]
EUNLINKqdbm::Villa [static]
EWRITEqdbm::Villa [static]
fatalerror()qdbm::Villa [virtual]
fetchrec(const Datum &key)qdbm::Villa [virtual]
firstkey()qdbm::Villa [virtual]
fsiz()qdbm::Villa [virtual]
get(const char *kbuf, int ksiz, int *sp=0)qdbm::Villa [virtual]
inode()qdbm::Villa [virtual]
JBACKWARDqdbm::Villa [static]
JFORWARDqdbm::Villa [static]
lnum()qdbm::Villa [virtual]
mtime()qdbm::Villa [virtual]
name()qdbm::Villa [virtual]
nextkey()qdbm::Villa [virtual]
nnum()qdbm::Villa [virtual]
OCREATqdbm::Villa [static]
OLCKNBqdbm::Villa [static]
ONOLCKqdbm::Villa [static]
optimize()qdbm::Villa [virtual]
OREADERqdbm::Villa [static]
OTRUNCqdbm::Villa [static]
out(const char *kbuf, int ksiz)qdbm::Villa [virtual]
OWRITERqdbm::Villa [static]
OXCOMPqdbm::Villa [static]
OYCOMPqdbm::Villa [static]
OZCOMPqdbm::Villa [static]
put(const char *kbuf, int ksiz, const char *vbuf, int vsiz, int dmode=Villa::DOVER)qdbm::Villa [virtual]
remove(const char *name)qdbm::Villa [static]
rnum()qdbm::Villa [virtual]
settuning(int lrecmax, int nidxmax, int lcnum, int ncnum)qdbm::Villa [virtual]
silentqdbm::Villa
storerec(const Datum &key, const Datum &val, bool replace=true)qdbm::Villa [virtual]
sync()qdbm::Villa [virtual]
tranabort()qdbm::Villa [virtual]
tranbegin()qdbm::Villa [virtual]
trancommit()qdbm::Villa [virtual]
version()qdbm::Villa [static]
Villa(const char *name, int omode=Villa::OREADER, VLCFUNC cmp=Villa::cmplex)qdbm::Villa
vnum(const char *kbuf, int ksiz)qdbm::Villa [virtual]
vsiz(const char *kbuf, int ksiz)qdbm::Villa [virtual]
writable()qdbm::Villa [virtual]
~ADBM()qdbm::ADBM [virtual]
~Villa()qdbm::Villa [virtual]
Generated on Thu Aug 5 02:15:30 2010 for QDBM for C++ by  doxygen 1.6.3
qdbm-1.8.78/plus/xapidoc/classqdbm_1_1Curia__error-members.html0000644000175000017500000001275411426320062023446 0ustar mikiomikio QDBM for C++: Member List

qdbm::Curia_error Member List

This is the complete list of members for qdbm::Curia_error, including all inherited members.
code() const qdbm::Curia_error [virtual]
Curia_error()qdbm::Curia_error
Curia_error(int ecode)qdbm::Curia_error
Curia_error(const Curia_error &ce)qdbm::Curia_error
DBM_error()qdbm::DBM_error
DBM_error(const char *message)qdbm::DBM_error
message() const qdbm::Curia_error [virtual]
operator const char *() const qdbm::Curia_error [virtual]
operator!=(const Curia_error &ce) const qdbm::Curia_error [virtual]
operator!=(int ecode) const qdbm::Curia_error [virtual]
operator=(const Curia_error &ce)qdbm::Curia_error
operator=(int ecode)qdbm::Curia_error
operator==(const Curia_error &ce) const qdbm::Curia_error [virtual]
operator==(int ecode) const qdbm::Curia_error [virtual]
~Curia_error()qdbm::Curia_error [virtual]
~DBM_error()qdbm::DBM_error [virtual]
Generated on Thu Aug 5 02:15:30 2010 for QDBM for C++ by  doxygen 1.6.3
qdbm-1.8.78/plus/xapidoc/functions_0x76.html0000644000175000017500000001033011426320062017631 0ustar mikiomikio QDBM for C++: Class Members
Here is a list of all documented class members with links to the class documentation for each member:

- v -

Generated on Thu Aug 5 02:15:30 2010 for QDBM for C++ by  doxygen 1.6.3
qdbm-1.8.78/plus/xapidoc/ftv2doc.png0000644000175000017500000000037711426320062016236 0ustar mikiomikio‰PNG  IHDR_Tq-PLTEÿÿÿÿÿÿÿÿÀÀÀ€€€ÿ³½ûÈtRNS@æØftEXtSoftwaregif2png 2.4.2£^GvIDATxÚc````c``d'0bqâ$8`qÊ'3001£2 pT2Si`q'Ê€\\À”¢ˆRKRSiÈ”„RRÅi 6त¤h‚ÄQ‚kqMaNUò`'E$pgc 0Åo#õÐàUƒG½IEND®B`‚qdbm-1.8.78/plus/xapidoc/namespacemembers_func.html0000644000175000017500000000325111426320062021363 0ustar mikiomikio QDBM for C++: Class Members
 
  • operator+() : qdbm
Generated on Thu Aug 5 02:15:30 2010 for QDBM for C++ by  doxygen 1.6.3
qdbm-1.8.78/plus/xapidoc/ftv2link.png0000644000175000017500000000054611426320062016424 0ustar mikiomikio‰PNG  IHDR_Tq-0PLTEÿÿÿ€ÿÿ€ÿ€€€€€ÀÀÀ~›tRNS@æØftEXtSoftwaregif2png 2.4.2£^G&tEXtCommentUlead GIF SmartSaver Ver 2.0Ù åJIDATxÚ}Œ± Â0Eo3´c~¡SW‹~€n®Z²¾:d5¸dì/Ÿy!PÐÉÍᾨ‚àf}ÀžQp@Ï­tÛbâ ÁÌa;j»;éhº¬Q$ìÜKhíÒ^~ý’¨m„²((8ÊÒLF-YÌ8\‹Ìãþ+qúy¼gy…TiÞÞ/øÏq•+¡xÐÿIEND®B`‚qdbm-1.8.78/plus/xapidoc/classqdbm_1_1ADBM.png0000644000175000017500000000117111426320062017715 0ustar mikiomikio‰PNG  IHDRPæûÚÿPLTEÿÿÿÿÿÀŸŸ`ÀÀÀ{ÂÿätRNSÿÿÿÿÿÿÿÕÊT2IDATxíÝÙ’Â EQ/]åÿr?0„f…* ›j5ð– ¯¯µE”Å]^ ²E$ €È® R‘­'‰¿ðíÝç9 bk›¿p­?oŸ"â†&¯—ر¹ë QDBM for C++: Class Members
Here is a list of all documented class members with links to the class documentation for each member:

- t -

Generated on Thu Aug 5 02:15:30 2010 for QDBM for C++ by  doxygen 1.6.3
qdbm-1.8.78/plus/xapidoc/functions_0x6f.html0000644000175000017500000002117711426320062017723 0ustar mikiomikio QDBM for C++: Class Members
Here is a list of all documented class members with links to the class documentation for each member:

- o -

Generated on Thu Aug 5 02:15:30 2010 for QDBM for C++ by  doxygen 1.6.3
qdbm-1.8.78/plus/xapidoc/index.html0000644000175000017500000000102411426320062016144 0ustar mikiomikio QDBM for C++ <body> <a href="main.html">Frames are disabled. Click here to go to the main page.</a> </body> qdbm-1.8.78/plus/xapidoc/ftv2pnode.png0000644000175000017500000000031011426320062016561 0ustar mikiomikio‰PNG  IHDRLƒ1Ù$PLTEÀÀÀ€€€S¾™tRNS@æØftEXtSoftwaregif2png 2.4.2£^G0IDATxÚc` .àBn&8ââTŠÊàÞ >DŒ›II‰››Y¦S;:ºk/ªËoIEND®B`‚qdbm-1.8.78/plus/xapidoc/classqdbm_1_1Villa.png0000644000175000017500000000075711426320062020272 0ustar mikiomikio‰PNG  IHDRTP°$¢åPLTEÿÿÿÿÿÀŸŸ`ÀÀÀ{ÂÿätRNSÿÿÿÿÿÿÿÕÊT2~IDATxíÛnÄ Dç)ÿÿÉ}° „$½(¤m$v½û`›Yòª%ƬgIff3í{˜e:ÓŠÊtf@ws˜qƒdfX÷#ýÕ1–Œ=c:+öv?Là̈+R²Âc0£c;4ó•H‹ïéìvþ¾¾Þ°ØÄÙ¸Ÿ³b>lÍa§)ÔÖ}rVëE¶/ò’2°ÖÑé´_ëØY£I=Ã{a4K}îtŠdd5êÀªýÎzZÿ«NQö/ûšµgMG–{eúŒ:­H¯%ÛÚåëyp¡ÓN¯;^jþ‡¶é´êoò=ÕÎyݧ/¸OïÛ¢x©Î|E÷ï靯öß?…nÛÔ' Ûöõè‹NAtAtAtA_å!æ—´ ¿E+>ëËN7 ×N#Ô5ß‚té¼|®ÏÈÚ€ùñ‰wÀ}Ê©æ<öî˜éhÆìÊŸýFùÇžNùDUŸAÏODP÷Ò‰NïÿÅ^ ]Wß?…>0>ýy ÊɧO*IEND®B`‚qdbm-1.8.78/plus/xapidoc/ftv2blank.png0000644000175000017500000000025611426320062016554 0ustar mikiomikio‰PNG  IHDR–ÖGtRNS”ý®tEXtSoftwaregif2png 2.4.2£^G%tEXtCommentUlead GIF SmartSaver Ver 2.0!ø×^SIDATxÚc8À€€0àBx<2Ër|IEND®B`‚qdbm-1.8.78/plus/xapidoc/functions_0x66.html0000644000175000017500000001141711426320062017637 0ustar mikiomikio QDBM for C++: Class Members
Here is a list of all documented class members with links to the class documentation for each member:

- f -

Generated on Thu Aug 5 02:15:30 2010 for QDBM for C++ by  doxygen 1.6.3
qdbm-1.8.78/plus/xapidoc/search/0000755000175000017500000000000011426320062015417 5ustar mikiomikioqdbm-1.8.78/plus/xapidoc/search/classes_63.html0000644000175000017500000000275711426320062020265 0ustar mikiomikio
Loading...
Curia qdbm
Searching...
No Matches
qdbm-1.8.78/plus/xapidoc/search/functions_7e.html0000644000175000017500000001045111426320062020711 0ustar mikiomikio
Loading...
~ADBM qdbm::ADBM
~Curia qdbm::Curia
~Curia_error qdbm::Curia_error
~Datum qdbm::Datum
~DBM_error qdbm::DBM_error
~Depot qdbm::Depot
~Depot_error qdbm::Depot_error
~Villa qdbm::Villa
~Villa_error qdbm::Villa_error
Searching...
No Matches
qdbm-1.8.78/plus/xapidoc/search/functions_62.html0000644000175000017500000000524311426320062020630 0ustar mikiomikio
Loading...
Searching...
No Matches
qdbm-1.8.78/plus/xapidoc/search/variables_6f.html0000644000175000017500000002522611426320062020657 0ustar mikiomikio qdbm-1.8.78/plus/xapidoc/search/all_73.html0000644000175000017500000002060611426320062017372 0ustar mikiomikio
Loading...
settuning qdbm::Villa
size qdbm::Datum
Searching...
No Matches
qdbm-1.8.78/plus/xapidoc/search/functions_70.html0000644000175000017500000000540711426320062020631 0ustar mikiomikio
Loading...
ptr qdbm::Datum
putlob qdbm::Curia
Searching...
No Matches
qdbm-1.8.78/plus/xapidoc/search/all_70.html0000644000175000017500000000540711426320062017371 0ustar mikiomikio
Loading...
ptr qdbm::Datum
putlob qdbm::Curia
Searching...
No Matches
qdbm-1.8.78/plus/xapidoc/search/all_76.html0000644000175000017500000001464011426320062017376 0ustar mikiomikio
Loading...
Villa qdbm::Villa
Villa qdbm
vnum qdbm::Villa
vsizlob qdbm::Curia
Searching...
No Matches
qdbm-1.8.78/plus/xapidoc/search/variables_64.html0000644000175000017500000001233711426320062020574 0ustar mikiomikio
Loading...
DDUP qdbm::Villa
DDUPR qdbm::Villa
Searching...
No Matches
qdbm-1.8.78/plus/xapidoc/search/all_67.html0000644000175000017500000000731111426320062017373 0ustar mikiomikio
Loading...
getlob qdbm::Curia
getlobfd qdbm::Curia
Searching...
No Matches
qdbm-1.8.78/plus/xapidoc/search/functions_73.html0000644000175000017500000001622711426320062020636 0ustar mikiomikio
Loading...
settuning qdbm::Villa
size qdbm::Datum
Searching...
No Matches
qdbm-1.8.78/plus/xapidoc/search/all_7e.html0000644000175000017500000001045111426320062017451 0ustar mikiomikio
Loading...
~ADBM qdbm::ADBM
~Curia qdbm::Curia
~Curia_error qdbm::Curia_error
~Datum qdbm::Datum
~DBM_error qdbm::DBM_error
~Depot qdbm::Depot
~Depot_error qdbm::Depot_error
~Villa qdbm::Villa
~Villa_error qdbm::Villa_error
Searching...
No Matches
qdbm-1.8.78/plus/xapidoc/search/all_63.html0000644000175000017500000003011611426320062017366 0ustar mikiomikio
Loading...
cmpdec qdbm::Villa
cmpint qdbm::Villa
cmplex qdbm::Villa
cmpnum qdbm::Villa
CPAFTER qdbm::Villa
CPBEFORE qdbm::Villa
CPCURRENT qdbm::Villa
curfirst qdbm::Villa
Curia qdbm
Curia qdbm::Curia
curjump qdbm::Villa
curkey qdbm::Villa
curlast qdbm::Villa
curnext qdbm::Villa
curout qdbm::Villa
curprev qdbm::Villa
curput qdbm::Villa
curval qdbm::Villa
Searching...
No Matches
qdbm-1.8.78/plus/xapidoc/search/functions_6d.html0000644000175000017500000000715711426320062020720 0ustar mikiomikio
Loading...
Searching...
No Matches
qdbm-1.8.78/plus/xapidoc/search/all_6f.html0000644000175000017500000006664511426320062017471 0ustar mikiomikio
Loading...
operator[] qdbm::Datum
ourmutex qdbm
outlob qdbm::Curia
OXCOMP qdbm::Villa
OYCOMP qdbm::Villa
OZCOMP qdbm::Villa
Searching...
No Matches
qdbm-1.8.78/plus/xapidoc/search/variables_65.html0000644000175000017500000006551111426320062020577 0ustar mikiomikio
Loading...
Searching...
No Matches
qdbm-1.8.78/plus/xapidoc/search/all_66.html0000644000175000017500000001616011426320062017374 0ustar mikiomikio
Loading...
fdesc qdbm::Depot
fsizd qdbm::Curia
Searching...
No Matches
qdbm-1.8.78/plus/xapidoc/search/functions_64.html0000644000175000017500000001454111426320062020633 0ustar mikiomikio qdbm-1.8.78/plus/xapidoc/search/all_62.html0000644000175000017500000000524311426320062017370 0ustar mikiomikio
Loading...
Searching...
No Matches
qdbm-1.8.78/plus/xapidoc/search/functions_6f.html0000644000175000017500000004272111426320062020716 0ustar mikiomikio
Loading...
operator[] qdbm::Datum
outlob qdbm::Curia
Searching...
No Matches
qdbm-1.8.78/plus/xapidoc/search/classes_64.html0000644000175000017500000000425211426320062020256 0ustar mikiomikio
Loading...
Datum qdbm
DBM_error qdbm
Depot qdbm
Searching...
No Matches
qdbm-1.8.78/plus/xapidoc/search/classes_61.html0000644000175000017500000000220111426320062020243 0ustar mikiomikio
Loading...
ADBM qdbm
Searching...
No Matches
qdbm-1.8.78/plus/xapidoc/search/functions_6c.html0000644000175000017500000000225311426320062020707 0ustar mikiomikio
Loading...
lnum qdbm::Villa
Searching...
No Matches
qdbm-1.8.78/plus/xapidoc/search/functions_69.html0000644000175000017500000000764511426320062020647 0ustar mikiomikio
Loading...
Searching...
No Matches
qdbm-1.8.78/plus/xapidoc/search/functions_63.html0000644000175000017500000002433611426320062020635 0ustar mikiomikio
Loading...
cmpdec qdbm::Villa
cmpint qdbm::Villa
cmplex qdbm::Villa
cmpnum qdbm::Villa
curfirst qdbm::Villa
Curia qdbm::Curia
curjump qdbm::Villa
curkey qdbm::Villa
curlast qdbm::Villa
curnext qdbm::Villa
curout qdbm::Villa
curprev qdbm::Villa
curput qdbm::Villa
curval qdbm::Villa
Searching...
No Matches
qdbm-1.8.78/plus/xapidoc/search/search.css0000644000175000017500000000740311426320062017402 0ustar mikiomikio/*---------------- Search Box */ #FSearchBox { float: left; } #MSearchBox { padding: 0px; margin: 0px; border: none; border: 1px solid #84B0C7; white-space: nowrap; -moz-border-radius: 8px; -webkit-border-top-left-radius: 8px; -webkit-border-top-right-radius: 8px; -webkit-border-bottom-left-radius: 8px; -webkit-border-bottom-right-radius: 8px; } #MSearchField { font: 9pt Arial, Verdana, sans-serif; color: #999999; background-color: #FFFFFF; font-style: normal; cursor: text; padding: 1px 1px; margin: 0px 6px 0px 0px; border: none; outline: none; vertical-align: middle; } .MSearchBoxActive #MSearchField { color: #000000; } #MSearchSelect { float : none; display : inline; background : none; font: 9pt Verdana, sans-serif; border: none; margin: 0px 0px 0px 6px; vertical-align: middle; padding: 0px 0px; } #MSearchClose { float : none; display : none; background : none; border: none; margin: 0px 4px 0px 0px; padding: 0px 0px; outline: none; } #MSearchCloseImg { vertical-align: middle; } .MSearchBoxLeft { display: block; text-align: left; float: left; margin-left: 6px; } .MSearchBoxRight { display: block; float: right; text-align: right; margin-right: 6px; } .MSearchBoxSpacer { font-size: 0px; clear: both; } .MSearchBoxRow { font-size: 0px; clear: both; } /*---------------- Search filter selection */ #MSearchSelectWindow { display: none; position: absolute; left: 0; top: 0; border: 1px solid #A0A0A0; background-color: #FAFAFA; z-index: 1; padding-top: 4px; padding-bottom: 4px; -moz-border-radius: 4px; -webkit-border-top-left-radius: 4px; -webkit-border-top-right-radius: 4px; -webkit-border-bottom-left-radius: 4px; -webkit-border-bottom-right-radius: 4px; -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); } .SelectItem { font: 8pt Arial, Verdana, sans-serif; padding-left: 2px; padding-right: 12px; border: 0px; } span.SelectionMark { margin-right: 4px; font-family: monospace; outline-style: none; text-decoration: none; } a.SelectItem { display: block; outline-style: none; color: #000000; text-decoration: none; padding-left: 6px; padding-right: 12px; } a.SelectItem:focus, a.SelectItem:active { color: #000000; outline-style: none; text-decoration: none; } a.SelectItem:hover { color: #FFFFFF; background-color: #2A50E4; outline-style: none; text-decoration: none; cursor: pointer; display: block; } /*---------------- Search results window */ iframe#MSearchResults { width: 60ex; height: 15em; } #MSearchResultsWindow { display: none; position: absolute; left: 0; top: 0; border: 1px solid #000000; background-color: #EEF3F5; } /* ----------------------------------- */ #SRIndex { clear:both; padding-bottom: 15px; } .SREntry { font-size: 10pt; padding-left: 1ex; } .SRPage .SREntry { font-size: 8pt; padding: 1px 5px; } body.SRPage { margin: 5px 2px; } .SRChildren { padding-left: 3ex; padding-bottom: .5em } .SRPage .SRChildren { display: none; } .SRSymbol { font-weight: bold; color: #153788; font-family: Arial, Verdana, sans-serif; text-decoration: none; outline: none; } a.SRScope { display: block; color: #153788; font-family: Arial, Verdana, sans-serif; text-decoration: none; outline: none; } a.SRSymbol:focus, a.SRSymbol:active, a.SRScope:focus, a.SRScope:active { text-decoration: underline; } .SRPage .SRStatus { padding: 2px 5px; font-size: 8pt; font-style: italic; } .SRResult { display: none; } qdbm-1.8.78/plus/xapidoc/search/functions_66.html0000644000175000017500000001616011426320062020634 0ustar mikiomikio
Loading...
fdesc qdbm::Depot
fsizd qdbm::Curia
Searching...
No Matches
qdbm-1.8.78/plus/xapidoc/search/all_61.html0000644000175000017500000000220111426320062017356 0ustar mikiomikio
Loading...
ADBM qdbm
Searching...
No Matches
qdbm-1.8.78/plus/xapidoc/search/all_71.html0000644000175000017500000000213111426320062017361 0ustar mikiomikio
Loading...
Searching...
No Matches
qdbm-1.8.78/plus/xapidoc/search/all_77.html0000644000175000017500000000405111426320062017372 0ustar mikiomikio
Loading...
Searching...
No Matches
qdbm-1.8.78/plus/xapidoc/search/functions_67.html0000644000175000017500000000731111426320062020633 0ustar mikiomikio
Loading...
getlob qdbm::Curia
getlobfd qdbm::Curia
Searching...
No Matches
qdbm-1.8.78/plus/xapidoc/search/close.png0000644000175000017500000000042111426320062017227 0ustar mikiomikio‰PNG  IHDR ©¬w&ØIDATuQ½F@ Ü Cë5¼§Cg3(ÐÞw{#*ß—ŸÛË&9Áƒ}ßͲ,ض çy"Š"ÄqŒ<Ï‘¦©æŽišÌ8ޏ®Kß¾6 C”e‰¢(Ä;Žã/‘/¨ÂBVÑxó<»/Ú¶EUUte,"¸ïëºÂgL}ߣ®kçÓ2VçSF1 ƒs•¨1“œÇãÔ ¶ DZÆÆwÍA½$I”ûYQ[Òíú Üo×uŸkÓ*A iWY(G™/0Ï{ûAÏ,ëë)el«n]? yEÂIEND®B`‚qdbm-1.8.78/plus/xapidoc/search/variables_63.html0000644000175000017500000000367511426320062020600 0ustar mikiomikio
Loading...
CPAFTER qdbm::Villa
CPBEFORE qdbm::Villa
CPCURRENT qdbm::Villa
Searching...
No Matches
qdbm-1.8.78/plus/xapidoc/search/variables_73.html0000644000175000017500000000403511426320062020570 0ustar mikiomikio
Loading...
Searching...
No Matches
qdbm-1.8.78/plus/xapidoc/search/all_72.html0000644000175000017500000000720311426320062017367 0ustar mikiomikio
Loading...
rnumlob qdbm::Curia
Searching...
No Matches
qdbm-1.8.78/plus/xapidoc/search/functions_76.html0000644000175000017500000001333711426320062020640 0ustar mikiomikio
Loading...
Villa qdbm::Villa
vnum qdbm::Villa
vsizlob qdbm::Curia
Searching...
No Matches
qdbm-1.8.78/plus/xapidoc/search/functions_77.html0000644000175000017500000000405111426320062020632 0ustar mikiomikio
Loading...
Searching...
No Matches
qdbm-1.8.78/plus/xapidoc/search/all_64.html0000644000175000017500000003030211426320062017364 0ustar mikiomikio qdbm-1.8.78/plus/xapidoc/search/search.js0000644000175000017500000005107511426320062017232 0ustar mikiomikio// Search script generated by doxygen // Copyright (C) 2009 by Dimitri van Heesch. // The code in this file is loosly based on main.js, part of Natural Docs, // which is Copyright (C) 2003-2008 Greg Valure // Natural Docs is licensed under the GPL. var indexSectionsWithContent = { 0: "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000111111101101111111110110000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", 1: "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000101100000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", 2: "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", 3: "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011111101001111101110110000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", 4: "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001110000100001000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" }; var indexSectionNames = { 0: "all", 1: "classes", 2: "namespaces", 3: "functions", 4: "variables" }; function convertToId(search) { var result = ''; for (i=0;i do a search { this.Search(); } } this.OnSearchSelectKey = function(evt) { var e = (evt) ? evt : window.event; // for IE if (e.keyCode==40 && this.searchIndex0) // Up { this.searchIndex--; this.OnSelectItem(this.searchIndex); } else if (e.keyCode==13 || e.keyCode==27) { this.OnSelectItem(this.searchIndex); this.CloseSelectionWindow(); this.DOMSearchField().focus(); } return false; } // --------- Actions // Closes the results window. this.CloseResultsWindow = function() { this.DOMPopupSearchResultsWindow().style.display = 'none'; this.DOMSearchClose().style.display = 'none'; this.Activate(false); } this.CloseSelectionWindow = function() { this.DOMSearchSelectWindow().style.display = 'none'; } // Performs a search. this.Search = function() { this.keyTimeout = 0; // strip leading whitespace var searchValue = this.DOMSearchField().value.replace(/^ +/, ""); var code = searchValue.toLowerCase().charCodeAt(0); var hexCode; if (code<16) { hexCode="0"+code.toString(16); } else { hexCode=code.toString(16); } var resultsPage; var resultsPageWithSearch; var hasResultsPage; if (indexSectionsWithContent[this.searchIndex].charAt(code) == '1') { resultsPage = this.resultsPath + '/' + indexSectionNames[this.searchIndex] + '_' + hexCode + '.html'; resultsPageWithSearch = resultsPage+'?'+escape(searchValue); hasResultsPage = true; } else // nothing available for this search term { resultsPage = this.resultsPath + '/nomatches.html'; resultsPageWithSearch = resultsPage; hasResultsPage = false; } window.frames.MSearchResults.location.href = resultsPageWithSearch; var domPopupSearchResultsWindow = this.DOMPopupSearchResultsWindow(); if (domPopupSearchResultsWindow.style.display!='block') { var domSearchBox = this.DOMSearchBox(); this.DOMSearchClose().style.display = 'inline'; if (this.insideFrame) { var domPopupSearchResults = this.DOMPopupSearchResults(); domPopupSearchResultsWindow.style.position = 'relative'; domPopupSearchResultsWindow.style.display = 'block'; var width = document.body.clientWidth - 8; // the -8 is for IE :-( domPopupSearchResultsWindow.style.width = width + 'px'; domPopupSearchResults.style.width = width + 'px'; } else { var domPopupSearchResults = this.DOMPopupSearchResults(); var left = getXPos(domSearchBox) + domSearchBox.offsetWidth; var top = getYPos(domSearchBox) + domSearchBox.offsetHeight + 1; domPopupSearchResultsWindow.style.display = 'block'; left -= domPopupSearchResults.offsetWidth; domPopupSearchResultsWindow.style.top = top + 'px'; domPopupSearchResultsWindow.style.left = left + 'px'; } } this.lastSearchValue = searchValue; this.lastResultsPage = resultsPage; } // -------- Activation Functions // Activates or deactivates the search panel, resetting things to // their default values if necessary. this.Activate = function(isActive) { if (isActive || // open it this.DOMPopupSearchResultsWindow().style.display == 'block' ) { this.DOMSearchBox().className = 'MSearchBoxActive'; var searchField = this.DOMSearchField(); if (searchField.value == this.searchLabel) // clear "Search" term upon entry { searchField.value = ''; this.searchActive = true; } } else if (!isActive) // directly remove the panel { this.DOMSearchBox().className = 'MSearchBoxInactive'; this.DOMSearchField().value = this.searchLabel; this.searchActive = false; this.lastSearchValue = '' this.lastResultsPage = ''; } } } // ----------------------------------------------------------------------- // The class that handles everything on the search results page. function SearchResults(name) { // The number of matches from the last run of . this.lastMatchCount = 0; this.lastKey = 0; this.repeatOn = false; // Toggles the visibility of the passed element ID. this.FindChildElement = function(id) { var parentElement = document.getElementById(id); var element = parentElement.firstChild; while (element && element!=parentElement) { if (element.nodeName == 'DIV' && element.className == 'SRChildren') { return element; } if (element.nodeName == 'DIV' && element.hasChildNodes()) { element = element.firstChild; } else if (element.nextSibling) { element = element.nextSibling; } else { do { element = element.parentNode; } while (element && element!=parentElement && !element.nextSibling); if (element && element!=parentElement) { element = element.nextSibling; } } } } this.Toggle = function(id) { var element = this.FindChildElement(id); if (element) { if (element.style.display == 'block') { element.style.display = 'none'; } else { element.style.display = 'block'; } } } // Searches for the passed string. If there is no parameter, // it takes it from the URL query. // // Always returns true, since other documents may try to call it // and that may or may not be possible. this.Search = function(search) { if (!search) // get search word from URL { search = window.location.search; search = search.substring(1); // Remove the leading '?' search = unescape(search); } search = search.replace(/^ +/, ""); // strip leading spaces search = search.replace(/ +$/, ""); // strip trailing spaces search = search.toLowerCase(); search = convertToId(search); var resultRows = document.getElementsByTagName("div"); var matches = 0; var i = 0; while (i < resultRows.length) { var row = resultRows.item(i); if (row.className == "SRResult") { var rowMatchName = row.id.toLowerCase(); rowMatchName = rowMatchName.replace(/^sr\d*_/, ''); // strip 'sr123_' if (search.length<=rowMatchName.length && rowMatchName.substr(0, search.length)==search) { row.style.display = 'block'; matches++; } else { row.style.display = 'none'; } } i++; } document.getElementById("Searching").style.display='none'; if (matches == 0) // no results { document.getElementById("NoMatches").style.display='block'; } else // at least one result { document.getElementById("NoMatches").style.display='none'; } this.lastMatchCount = matches; return true; } // return the first item with index index or higher that is visible this.NavNext = function(index) { var focusItem; while (1) { var focusName = 'Item'+index; focusItem = document.getElementById(focusName); if (focusItem && focusItem.parentNode.parentNode.style.display=='block') { break; } else if (!focusItem) // last element { break; } focusItem=null; index++; } return focusItem; } this.NavPrev = function(index) { var focusItem; while (1) { var focusName = 'Item'+index; focusItem = document.getElementById(focusName); if (focusItem && focusItem.parentNode.parentNode.style.display=='block') { break; } else if (!focusItem) // last element { break; } focusItem=null; index--; } return focusItem; } this.ProcessKeys = function(e) { if (e.type == "keydown") { this.repeatOn = false; this.lastKey = e.keyCode; } else if (e.type == "keypress") { if (!this.repeatOn) { if (this.lastKey) this.repeatOn = true; return false; // ignore first keypress after keydown } } else if (e.type == "keyup") { this.lastKey = 0; this.repeatOn = false; } return this.lastKey!=0; } this.Nav = function(evt,itemIndex) { var e = (evt) ? evt : window.event; // for IE if (e.keyCode==13) return true; if (!this.ProcessKeys(e)) return false; if (this.lastKey==38) // Up { var newIndex = itemIndex-1; var focusItem = this.NavPrev(newIndex); if (focusItem) { var child = this.FindChildElement(focusItem.parentNode.parentNode.id); if (child && child.style.display == 'block') // children visible { var n=0; var tmpElem; while (1) // search for last child { tmpElem = document.getElementById('Item'+newIndex+'_c'+n); if (tmpElem) { focusItem = tmpElem; } else // found it! { break; } n++; } } } if (focusItem) { focusItem.focus(); } else // return focus to search field { parent.document.getElementById("MSearchField").focus(); } } else if (this.lastKey==40) // Down { var newIndex = itemIndex+1; var focusItem; var item = document.getElementById('Item'+itemIndex); var elem = this.FindChildElement(item.parentNode.parentNode.id); if (elem && elem.style.display == 'block') // children visible { focusItem = document.getElementById('Item'+itemIndex+'_c0'); } if (!focusItem) focusItem = this.NavNext(newIndex); if (focusItem) focusItem.focus(); } else if (this.lastKey==39) // Right { var item = document.getElementById('Item'+itemIndex); var elem = this.FindChildElement(item.parentNode.parentNode.id); if (elem) elem.style.display = 'block'; } else if (this.lastKey==37) // Left { var item = document.getElementById('Item'+itemIndex); var elem = this.FindChildElement(item.parentNode.parentNode.id); if (elem) elem.style.display = 'none'; } else if (this.lastKey==27) // Escape { parent.searchBox.CloseResultsWindow(); parent.document.getElementById("MSearchField").focus(); } else if (this.lastKey==13) // Enter { return true; } return false; } this.NavChild = function(evt,itemIndex,childIndex) { var e = (evt) ? evt : window.event; // for IE if (e.keyCode==13) return true; if (!this.ProcessKeys(e)) return false; if (this.lastKey==38) // Up { if (childIndex>0) { var newIndex = childIndex-1; document.getElementById('Item'+itemIndex+'_c'+newIndex).focus(); } else // already at first child, jump to parent { document.getElementById('Item'+itemIndex).focus(); } } else if (this.lastKey==40) // Down { var newIndex = childIndex+1; var elem = document.getElementById('Item'+itemIndex+'_c'+newIndex); if (!elem) // last child, jump to parent next parent { elem = this.NavNext(itemIndex+1); } if (elem) { elem.focus(); } } else if (this.lastKey==27) // Escape { parent.searchBox.CloseResultsWindow(); parent.document.getElementById("MSearchField").focus(); } else if (this.lastKey==13) // Enter { return true; } return false; } } qdbm-1.8.78/plus/xapidoc/search/functions_65.html0000644000175000017500000000450611426320062020634 0ustar mikiomikio
Loading...
Searching...
No Matches
qdbm-1.8.78/plus/xapidoc/search/all_65.html0000644000175000017500000007056511426320062017404 0ustar mikiomikio
Loading...
Searching...
No Matches
qdbm-1.8.78/plus/xapidoc/search/search.png0000644000175000017500000000101711426320062017371 0ustar mikiomikio‰PNG  IHDR™zÈLÖIDAT(’»®AQ†Ïf "D#J·Ð qI¼‚Â+ Ö)tBëDACE'H‘QºB!‘—󱜗“3ÅÚ³fþÿŸY3[º^¯_w»\.ÒÝÄõ?§¬0;N¿ßŸN§DÜn·ßï‡ÃKH§Ó‰zÕjµ\.ŸÏgêCP©Tjµ:‘HÄãq²Ÿ$dp­V«T* †P(äõz‡Ãv»MÐb±D£ÑdÝn—ú‘H„:Z­–RN§ÑZ­FŠæñßòU l2™pRÖh4êõzN‡ÃU¤ÞÒDP!ÞIMY~Ì#‚6ŠÅâo•T*ÅoýÐ$g¯×CHApÅw¹\œà@+Ùd2)Fs#û|>Îf³Y©TV«Õr¹Äi4Ù™˜6èt:M¦ÀãKtµÛíØS½^§m&ÊÎ!¥l6[.—3™L±Á` 0¹ªóù<»Ýn6›A#ßãñ°¡ívKãñ8 2ÐV«õ¦ñc’x uöûýáp5 Š›Í¦P(¬×k‡Ã‘ÍfYÁëñ½µ-^… ¦\ ¢µX,࣒ÉdÀ3Ypÿ)G þ|>ŸÍf±XŒ_à öhÜSB?̵¿þg2Ðß ¿¶ðVú!6ÓMæIEND®B`‚qdbm-1.8.78/plus/xapidoc/search/functions_74.html0000644000175000017500000000370511426320062020634 0ustar mikiomikio
Loading...
tranabort qdbm::Villa
tranbegin qdbm::Villa
trancommit qdbm::Villa
Searching...
No Matches
qdbm-1.8.78/plus/xapidoc/search/all_74.html0000644000175000017500000000370511426320062017374 0ustar mikiomikio
Loading...
tranabort qdbm::Villa
tranbegin qdbm::Villa
trancommit qdbm::Villa
Searching...
No Matches
qdbm-1.8.78/plus/xapidoc/search/all_6c.html0000644000175000017500000000225311426320062017447 0ustar mikiomikio
Loading...
lnum qdbm::Villa
Searching...
No Matches
qdbm-1.8.78/plus/xapidoc/search/functions_72.html0000644000175000017500000000720311426320062020627 0ustar mikiomikio
Loading...
rnumlob qdbm::Curia
Searching...
No Matches
qdbm-1.8.78/plus/xapidoc/search/namespaces_71.html0000644000175000017500000000213111426320062020730 0ustar mikiomikio
Loading...
Searching...
No Matches
qdbm-1.8.78/plus/xapidoc/search/nomatches.html0000644000175000017500000000071511426320062020271 0ustar mikiomikio
No Matches
qdbm-1.8.78/plus/xapidoc/search/all_6a.html0000644000175000017500000000307211426320062017445 0ustar mikiomikio
Loading...
JBACKWARD qdbm::Villa
JFORWARD qdbm::Villa
Searching...
No Matches
qdbm-1.8.78/plus/xapidoc/search/classes_76.html0000644000175000017500000000275711426320062020271 0ustar mikiomikio
Loading...
Villa qdbm
Searching...
No Matches
qdbm-1.8.78/plus/xapidoc/search/functions_6e.html0000644000175000017500000000766411426320062020724 0ustar mikiomikio
Loading...
nnum qdbm::Villa
Searching...
No Matches
qdbm-1.8.78/plus/xapidoc/search/variables_6a.html0000644000175000017500000000307211426320062020645 0ustar mikiomikio
Loading...
JBACKWARD qdbm::Villa
JFORWARD qdbm::Villa
Searching...
No Matches
qdbm-1.8.78/plus/xapidoc/search/all_69.html0000644000175000017500000000764511426320062017407 0ustar mikiomikio
Loading...
Searching...
No Matches
qdbm-1.8.78/plus/xapidoc/search/all_6e.html0000644000175000017500000000766411426320062017464 0ustar mikiomikio
Loading...
nnum qdbm::Villa
Searching...
No Matches
qdbm-1.8.78/plus/xapidoc/search/all_6d.html0000644000175000017500000000715711426320062017460 0ustar mikiomikio
Loading...
Searching...
No Matches
qdbm-1.8.78/plus/xapidoc/classqdbm_1_1Curia__error.html0000644000175000017500000004465411426320062022022 0ustar mikiomikio QDBM for C++: qdbm::Curia_error Class Reference

qdbm::Curia_error Class Reference

Error container for Curia. More...

Inheritance diagram for qdbm::Curia_error:
qdbm::DBM_error

List of all members.

Public Member Functions

 Curia_error () throw ()
 Create an instance.
 Curia_error (int ecode) throw ()
 Create an instance.
 Curia_error (const Curia_error &ce) throw ()
 Copy constructor.
virtual ~Curia_error () throw ()
 Release resources of the instance.
Curia_erroroperator= (const Curia_error &ce) throw ()
 Assignment operator.
Curia_erroroperator= (int ecode) throw ()
 Assignment operator.
virtual bool operator== (const Curia_error &ce) const throw ()
 Equality operator.
virtual bool operator!= (const Curia_error &ce) const throw ()
 Inequality operator.
virtual bool operator== (int ecode) const throw ()
 Equality operator.
virtual bool operator!= (int ecode) const throw ()
 Inequality operator.
virtual operator const char * () const throw ()
 Cast operator into pointer to char.
virtual int code () const throw ()
 Get the error code.
virtual const char * message () const throw ()
 Get the error message.

Detailed Description

Error container for Curia.


Constructor & Destructor Documentation

qdbm::Curia_error::Curia_error ( int  ecode  )  throw ()

Create an instance.

Parameters:
ecode the error code.
qdbm::Curia_error::Curia_error ( const Curia_error ce  )  throw ()

Copy constructor.

Parameters:
ce a source instance.

Member Function Documentation

virtual int qdbm::Curia_error::code (  )  const throw () [virtual]

Get the error code.

Returns:
the error code.
virtual const char* qdbm::Curia_error::message (  )  const throw () [virtual]

Get the error message.

Returns:
the pointer to the string.

Reimplemented from qdbm::DBM_error.

virtual qdbm::Curia_error::operator const char * (  )  const throw () [virtual]

Cast operator into pointer to char.

Returns:
the pointer to the string.

Reimplemented from qdbm::DBM_error.

virtual bool qdbm::Curia_error::operator!= ( int  ecode  )  const throw () [virtual]

Inequality operator.

Parameters:
ecode a comparing error code.
Returns:
true if both do not equal, else, false.
virtual bool qdbm::Curia_error::operator!= ( const Curia_error ce  )  const throw () [virtual]

Inequality operator.

Parameters:
ce a comparing instance.
Returns:
true if both do not equal, else, false.
Curia_error& qdbm::Curia_error::operator= ( int  ecode  )  throw ()

Assignment operator.

Parameters:
ecode the error code.
Returns:
reference to itself.
Curia_error& qdbm::Curia_error::operator= ( const Curia_error ce  )  throw ()

Assignment operator.

Parameters:
ce a source instance.
Returns:
reference to itself.
virtual bool qdbm::Curia_error::operator== ( int  ecode  )  const throw () [virtual]

Equality operator.

Parameters:
ecode a comparing error code.
Returns:
true if both equal, else, false.
virtual bool qdbm::Curia_error::operator== ( const Curia_error ce  )  const throw () [virtual]

Equality operator.

Parameters:
ce a comparing instance.
Returns:
true if both equal, else, false.

The documentation for this class was generated from the following file:
  • xcuria.h
Generated on Thu Aug 5 02:15:30 2010 for QDBM for C++ by  doxygen 1.6.3
qdbm-1.8.78/plus/xapidoc/classqdbm_1_1DBM__error.html0000644000175000017500000001770611426320062021357 0ustar mikiomikio QDBM for C++: qdbm::DBM_error Class Reference

qdbm::DBM_error Class Reference

Error container for ADBM. More...

Inheritance diagram for qdbm::DBM_error:
qdbm::Curia_error qdbm::Depot_error qdbm::Villa_error

List of all members.

Public Member Functions

 DBM_error () throw ()
 Create an instance.
 DBM_error (const char *message) throw ()
 Create an instance.
virtual ~DBM_error () throw ()
 Release resources of the instance.
virtual operator const char * () const throw ()
 Cast operator into pointer to char.
virtual const char * message () const throw ()
 Get the message.

Detailed Description

Error container for ADBM.


Constructor & Destructor Documentation

qdbm::DBM_error::DBM_error ( const char *  message  )  throw ()

Create an instance.

Parameters:
message the string of a error message.

Member Function Documentation

virtual const char* qdbm::DBM_error::message (  )  const throw () [virtual]

Get the message.

Returns:
the pointer to the string.

Reimplemented in qdbm::Curia_error, qdbm::Depot_error, and qdbm::Villa_error.

virtual qdbm::DBM_error::operator const char * (  )  const throw () [virtual]

Cast operator into pointer to char.

Returns:
the pointer to the string.

Reimplemented in qdbm::Curia_error, qdbm::Depot_error, and qdbm::Villa_error.


The documentation for this class was generated from the following file:
  • xadbm.h
Generated on Thu Aug 5 02:15:30 2010 for QDBM for C++ by  doxygen 1.6.3
qdbm-1.8.78/plus/xapidoc/functions_0x67.html0000644000175000017500000000757611426320062017653 0ustar mikiomikio QDBM for C++: Class Members
Here is a list of all documented class members with links to the class documentation for each member:

- g -

Generated on Thu Aug 5 02:15:30 2010 for QDBM for C++ by  doxygen 1.6.3
qdbm-1.8.78/plus/xapidoc/functions_0x70.html0000644000175000017500000000724511426320062017636 0ustar mikiomikio QDBM for C++: Class Members
Here is a list of all documented class members with links to the class documentation for each member:

- p -

Generated on Thu Aug 5 02:15:30 2010 for QDBM for C++ by  doxygen 1.6.3
qdbm-1.8.78/plus/xapidoc/classqdbm_1_1Villa__error.html0000644000175000017500000004464611426320062022027 0ustar mikiomikio QDBM for C++: qdbm::Villa_error Class Reference

qdbm::Villa_error Class Reference

Error container for Villa. More...

Inheritance diagram for qdbm::Villa_error:
qdbm::DBM_error

List of all members.

Public Member Functions

 Villa_error () throw ()
 Create an instance.
 Villa_error (int ecode) throw ()
 Create an instance.
 Villa_error (const Villa_error &ve) throw ()
 Copy constructor.
virtual ~Villa_error () throw ()
 Release resources of the instance.
Villa_erroroperator= (const Villa_error &ve) throw ()
 Assignment operator.
Villa_erroroperator= (int ecode) throw ()
 Assignment operator.
virtual bool operator== (const Villa_error &ve) const throw ()
 Equality operator.
virtual bool operator!= (const Villa_error &ve) const throw ()
 Inequality operator.
virtual bool operator== (int ecode) const throw ()
 Equality operator.
virtual bool operator!= (int ecode) const throw ()
 Inequality operator.
virtual operator const char * () const throw ()
 Cast operator into pointer to char.
virtual int code () const throw ()
 Get the error code.
virtual const char * message () const throw ()
 Get the error message.

Detailed Description

Error container for Villa.


Constructor & Destructor Documentation

qdbm::Villa_error::Villa_error ( int  ecode  )  throw ()

Create an instance.

Parameters:
ecode the error code.
qdbm::Villa_error::Villa_error ( const Villa_error ve  )  throw ()

Copy constructor.

Parameters:
ve a source instance.

Member Function Documentation

virtual int qdbm::Villa_error::code (  )  const throw () [virtual]

Get the error code.

Returns:
the error code.
virtual const char* qdbm::Villa_error::message (  )  const throw () [virtual]

Get the error message.

Returns:
the pointer to the string.

Reimplemented from qdbm::DBM_error.

virtual qdbm::Villa_error::operator const char * (  )  const throw () [virtual]

Cast operator into pointer to char.

Returns:
the pointer to the string.

Reimplemented from qdbm::DBM_error.

virtual bool qdbm::Villa_error::operator!= ( int  ecode  )  const throw () [virtual]

Inequality operator.

Parameters:
ecode a comparing error code.
Returns:
true if both do not equal, else, false.
virtual bool qdbm::Villa_error::operator!= ( const Villa_error ve  )  const throw () [virtual]

Inequality operator.

Parameters:
ve a comparing instance.
Returns:
true if both do not equal, else, false.
Villa_error& qdbm::Villa_error::operator= ( int  ecode  )  throw ()

Assignment operator.

Parameters:
ecode the error code.
Returns:
reference to itself.
Villa_error& qdbm::Villa_error::operator= ( const Villa_error ve  )  throw ()

Assignment operator.

Parameters:
ve a source instance.
Returns:
reference to itself.
virtual bool qdbm::Villa_error::operator== ( int  ecode  )  const throw () [virtual]

Equality operator.

Parameters:
ecode a comparing error code.
Returns:
true if both equal, else, false.
virtual bool qdbm::Villa_error::operator== ( const Villa_error ve  )  const throw () [virtual]

Equality operator.

Parameters:
ve a comparing instance.
Returns:
true if both equal, else, false.

The documentation for this class was generated from the following file:
  • xvilla.h
Generated on Thu Aug 5 02:15:30 2010 for QDBM for C++ by  doxygen 1.6.3
qdbm-1.8.78/plus/xapidoc/functions_0x6a.html0000644000175000017500000000656611426320062017723 0ustar mikiomikio QDBM for C++: Class Members
Here is a list of all documented class members with links to the class documentation for each member:

- j -

Generated on Thu Aug 5 02:15:30 2010 for QDBM for C++ by  doxygen 1.6.3
qdbm-1.8.78/plus/xapidoc/doxygen.css0000644000175000017500000001734711426320062016355 0ustar mikiomikio/* The standard CSS for doxygen */ body, table, div, p, dl { font-family: Lucida Grande, Verdana, Geneva, Arial, sans-serif; font-size: 12px; } /* @group Heading Levels */ h1 { text-align: center; font-size: 150%; } h2 { font-size: 120%; } h3 { font-size: 100%; } dt { font-weight: bold; } div.multicol { -moz-column-gap: 1em; -webkit-column-gap: 1em; -moz-column-count: 3; -webkit-column-count: 3; } p.startli, p.startdd, p.starttd { margin-top: 2px; } p.endli { margin-bottom: 0px; } p.enddd { margin-bottom: 4px; } p.endtd { margin-bottom: 2px; } /* @end */ caption { font-weight: bold; } span.legend { font-size: 70%; text-align: center; } h3.version { font-size: 90%; text-align: center; } div.qindex, div.navtab{ background-color: #e8eef2; border: 1px solid #84b0c7; text-align: center; margin: 2px; padding: 2px; } div.qindex, div.navpath { width: 100%; line-height: 140%; } div.navtab { margin-right: 15px; } /* @group Link Styling */ a { color: #153788; font-weight: normal; text-decoration: none; } .contents a:visited { color: #1b77c5; } a:hover { text-decoration: underline; } a.qindex { font-weight: bold; } a.qindexHL { font-weight: bold; background-color: #6666cc; color: #ffffff; border: 1px double #9295C2; } .contents a.qindexHL:visited { color: #ffffff; } a.el { font-weight: bold; } a.elRef { } a.code { color: #3030f0; } a.codeRef { color: #3030f0; } /* @end */ dl.el { margin-left: -1cm; } .fragment { font-family: monospace, fixed; font-size: 105%; } pre.fragment { border: 1px solid #CCCCCC; background-color: #f5f5f5; padding: 4px 6px; margin: 4px 8px 4px 2px; overflow: auto; word-wrap: break-word; font-size: 9pt; line-height: 125%; } div.ah { background-color: black; font-weight: bold; color: #ffffff; margin-bottom: 3px; margin-top: 3px } div.groupHeader { margin-left: 16px; margin-top: 12px; margin-bottom: 6px; font-weight: bold; } div.groupText { margin-left: 16px; font-style: italic; } body { background: white; color: black; margin-right: 20px; margin-left: 20px; } td.indexkey { background-color: #e8eef2; font-weight: bold; border: 1px solid #CCCCCC; margin: 2px 0px 2px 0; padding: 2px 10px; } td.indexvalue { background-color: #e8eef2; border: 1px solid #CCCCCC; padding: 2px 10px; margin: 2px 0px; } tr.memlist { background-color: #f0f0f0; } p.formulaDsp { text-align: center; } img.formulaDsp { } img.formulaInl { vertical-align: middle; } div.center { text-align: center; margin-top: 0px; margin-bottom: 0px; padding: 0px; } div.center img { border: 0px; } img.footer { border: 0px; vertical-align: middle; } /* @group Code Colorization */ span.keyword { color: #008000 } span.keywordtype { color: #604020 } span.keywordflow { color: #e08000 } span.comment { color: #800000 } span.preprocessor { color: #806020 } span.stringliteral { color: #002080 } span.charliteral { color: #008080 } span.vhdldigit { color: #ff00ff } span.vhdlchar { color: #000000 } span.vhdlkeyword { color: #700070 } span.vhdllogic { color: #ff0000 } /* @end */ .search { color: #003399; font-weight: bold; } form.search { margin-bottom: 0px; margin-top: 0px; } input.search { font-size: 75%; color: #000080; font-weight: normal; background-color: #e8eef2; } td.tiny { font-size: 75%; } .dirtab { padding: 4px; border-collapse: collapse; border: 1px solid #84b0c7; } th.dirtab { background: #e8eef2; font-weight: bold; } hr { height: 0px; border: none; border-top: 1px solid #666; } hr.footer { height: 1px; } /* @group Member Descriptions */ .mdescLeft, .mdescRight, .memItemLeft, .memItemRight, .memTemplItemLeft, .memTemplItemRight, .memTemplParams { background-color: #FAFAFA; border: none; margin: 4px; padding: 1px 0 0 8px; } .mdescLeft, .mdescRight { padding: 0px 8px 4px 8px; color: #555; } .memItemLeft, .memItemRight, .memTemplParams { border-top: 1px solid #ccc; } .memItemLeft, .memTemplItemLeft { white-space: nowrap; } .memTemplParams { color: #606060; white-space: nowrap; } /* @end */ /* @group Member Details */ /* Styles for detailed member documentation */ .memtemplate { font-size: 80%; color: #606060; font-weight: normal; margin-left: 3px; } .memnav { background-color: #e8eef2; border: 1px solid #84b0c7; text-align: center; margin: 2px; margin-right: 15px; padding: 2px; } .memitem { padding: 0; margin-bottom: 10px; } .memname { white-space: nowrap; font-weight: bold; margin-left: 6px; } .memproto { border-top: 1px solid #84b0c7; border-left: 1px solid #84b0c7; border-right: 1px solid #84b0c7; padding: 0; background-color: #d5e1e8; font-weight: bold; /* firefox specific markup */ background-image: -moz-linear-gradient(rgba(228, 233, 245, 1.0) 0%, rgba(193, 205, 232, 1.0) 100%); -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; -moz-border-radius-topright: 8px; -moz-border-radius-topleft: 8px; /* webkit specific markup */ background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, from(rgba(228, 233, 245, 1.0)), to(rgba(193, 205, 232, 1.0))); -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); -webkit-border-top-right-radius: 8px; -webkit-border-top-left-radius: 8px; } .memdoc { border-bottom: 1px solid #84b0c7; border-left: 1px solid #84b0c7; border-right: 1px solid #84b0c7; padding: 2px 5px; background-color: #eef3f5; border-top-width: 0; /* firefox specific markup */ -moz-border-radius-bottomleft: 8px; -moz-border-radius-bottomright: 8px; -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; /* webkit specific markup */ -webkit-border-bottom-left-radius: 8px; -webkit-border-bottom-right-radius: 8px; -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); } .paramkey { text-align: right; } .paramtype { white-space: nowrap; } .paramname { color: #602020; white-space: nowrap; } .paramname em { font-style: normal; } /* @end */ /* @group Directory (tree) */ /* for the tree view */ .ftvtree { font-family: sans-serif; margin: 0.5em; } /* these are for tree view when used as main index */ .directory { font-size: 9pt; font-weight: bold; } .directory h3 { margin: 0px; margin-top: 1em; font-size: 11pt; } /* The following two styles can be used to replace the root node title with an image of your choice. Simply uncomment the next two styles, specify the name of your image and be sure to set 'height' to the proper pixel height of your image. */ /* .directory h3.swap { height: 61px; background-repeat: no-repeat; background-image: url("yourimage.gif"); } .directory h3.swap span { display: none; } */ .directory > h3 { margin-top: 0; } .directory p { margin: 0px; white-space: nowrap; } .directory div { display: none; margin: 0px; } .directory img { vertical-align: -30%; } /* these are for tree view when not used as main index */ .directory-alt { font-size: 100%; font-weight: bold; } .directory-alt h3 { margin: 0px; margin-top: 1em; font-size: 11pt; } .directory-alt > h3 { margin-top: 0; } .directory-alt p { margin: 0px; white-space: nowrap; } .directory-alt div { display: none; margin: 0px; } .directory-alt img { vertical-align: -30%; } /* @end */ address { font-style: normal; color: #333; } table.doxtable { border-collapse:collapse; } table.doxtable td, table.doxtable th { border: 1px solid #153788; padding: 3px 7px 2px; } table.doxtable th { background-color: #254798; color: #FFFFFF; font-size: 110%; padding-bottom: 4px; padding-top: 5px; text-align:left; } qdbm-1.8.78/plus/xapidoc/namespaces.html0000644000175000017500000000277411426320062017171 0ustar mikiomikio QDBM for C++: Namespace Index

Namespace List

Here is a list of all documented namespaces with brief descriptions:
qdbmNamespace of QDBM
Generated on Thu Aug 5 02:15:30 2010 for QDBM for C++ by  doxygen 1.6.3
qdbm-1.8.78/plus/xapidoc/classqdbm_1_1Curia.html0000644000175000017500000031305211426320062020441 0ustar mikiomikio QDBM for C++: qdbm::Curia Class Reference

qdbm::Curia Class Reference

C++ API of Curia, the extended API of QDBM. More...

Inheritance diagram for qdbm::Curia:
qdbm::ADBM

List of all members.

Public Member Functions

 Curia (const char *name, int omode=Curia::OREADER, int bnum=-1, int dnum=-1) throw (Curia_error)
 Get the database handle.
virtual ~Curia () throw ()
 Release the resources.
virtual void close () throw (Curia_error)
 Close the database handle.
virtual bool put (const char *kbuf, int ksiz, const char *vbuf, int vsiz, int dmode=Curia::DOVER) throw (Curia_error)
 Store a record.
virtual bool out (const char *kbuf, int ksiz) throw (Curia_error)
 Delete a record.
virtual char * get (const char *kbuf, int ksiz, int start=0, int max=-1, int *sp=0) throw (Curia_error)
 Retrieve a record.
virtual int getwb (const char *kbuf, int ksiz, int start, int max, char *vbuf) throw (Curia_error)
 Retrieve a record and write the value into a buffer.
virtual int vsiz (const char *kbuf, int ksiz) throw (Curia_error)
 Get the size of the value of a record.
virtual void iterinit () throw (Curia_error)
 Initialize the iterator of the database handle.
virtual char * iternext (int *sp=0) throw (Curia_error)
 Get the next key of the iterator.
virtual void setalign (int align) throw (Curia_error)
 Set alignment of the database handle.
virtual void setfbpsiz (int size) throw (Curia_error)
 Set the size of the free block pool.
virtual void sync () throw (Curia_error)
 Synchronize updating contents with the files and the devices.
virtual void optimize (int bnum=-1) throw (Curia_error)
 Optimize the database.
virtual char * name () throw (Curia_error)
 Get the name of the database.
virtual int fsiz () throw (Curia_error)
 Get the total size of database files.
virtual double fsizd () throw (Curia_error)
 Get the total size of database files as double-precision floating-point number.
virtual int bnum () throw (Curia_error)
 Get the total number of the elements of each bucket array.
virtual int busenum () throw (Curia_error)
 Get the total number of the used elements of each bucket array.
virtual int rnum () throw (Curia_error)
 Get the number of the records stored in the database.
virtual bool writable () throw (Curia_error)
 Check whether the database handle is a writer or not.
virtual bool fatalerror () throw (Curia_error)
 Check whether the database has a fatal error or not.
virtual int inode () throw (Curia_error)
 Get the inode number of the database directory.
virtual time_t mtime () throw (Curia_error)
 Get the last modified time of the database.
virtual bool putlob (const char *kbuf, int ksiz, const char *vbuf, int vsiz, int dmode=Curia::DOVER) throw (Curia_error)
 Store a large object.
virtual bool outlob (const char *kbuf, int ksiz) throw (Curia_error)
 Delete a large object.
virtual char * getlob (const char *kbuf, int ksiz, int start=0, int max=-1, int *sp=0) throw (Curia_error)
 Retrieve a large object.
virtual int getlobfd (const char *kbuf, int ksiz)
 Get the file descriptor of a large object.
virtual int vsizlob (const char *kbuf, int ksiz) throw (Curia_error)
 Get the size of the value of a large object.
virtual int rnumlob () throw (Curia_error)
 Get the number of the large objects stored in the database.
virtual void storerec (const Datum &key, const Datum &val, bool replace=true) throw (Curia_error)
 Store a record.
virtual void deleterec (const Datum &key) throw (Curia_error)
 Delete a record.
virtual Datum fetchrec (const Datum &key) throw (Curia_error)
 Fetch a record.
virtual Datum firstkey () throw (Curia_error)
 Get the first key.
virtual Datum nextkey () throw (Curia_error)
 Get the next key.
virtual bool error () throw (Curia_error)
 Check whether a fatal error occured or not.

Static Public Member Functions

static const char * version () throw ()
 Get the version information.
static void remove (const char *name) throw (Curia_error)
 Remove a database directory.
static char * snaffle (const char *name, const char *kbuf, int ksiz, int *sp) throw (Curia_error)
 Retrieve a record directly from a database directory.

Public Attributes

bool silent
 whether to repress frequent exceptions

Static Public Attributes

static const int ENOERR
 error code: no error
static const int EFATAL
 error code: with fatal error
static const int EMODE
 error code: invalid mode
static const int EBROKEN
 error code: broken database file
static const int EKEEP
 error code: existing record
static const int ENOITEM
 error code: no item found
static const int EALLOC
 error code: memory allocation error
static const int EMAP
 error code: memory mapping error
static const int EOPEN
 error code: open error
static const int ECLOSE
 error code: close error
static const int ETRUNC
 error code: trunc error
static const int ESYNC
 error code: sync error
static const int ESTAT
 error code: stat error
static const int ESEEK
 error code: seek error
static const int EREAD
 error code: read error
static const int EWRITE
 error code: write error
static const int ELOCK
 error code: lock error
static const int EUNLINK
 error code: unlink error
static const int EMKDIR
 error code: mkdir error
static const int ERMDIR
 error code: rmdir error
static const int EMISC
 error code: miscellaneous error
static const int OREADER
 open mode: open as a reader
static const int OWRITER
 open mode: open as a writer
static const int OCREAT
 open mode: writer creating
static const int OTRUNC
 open mode: writer truncating
static const int ONOLCK
 open mode: open without locking
static const int OLCKNB
 open mode: lock without blocking
static const int OSPARSE
 open mode: create as sparse files
static const int DOVER
 write mode: overwrite the existing value
static const int DKEEP
 write mode: keep the existing value
static const int DCAT
 write mode: concatenate values

Detailed Description

C++ API of Curia, the extended API of QDBM.


Constructor & Destructor Documentation

qdbm::Curia::Curia ( const char *  name,
int  omode = Curia::OREADER,
int  bnum = -1,
int  dnum = -1 
) throw (Curia_error)

Get the database handle.

Parameters:
name the name of a database directory.
omode the connection mode: `CuriaOWRITER' as a writer, `CuriaOREADER' as a reader. If the mode is `CuriaOWRITER', the following may be added by bitwise or: `CuriaOCREAT', which means it creates a new database if not exist, `CuriaOTRUNC', which means it creates a new database regardless if one exists. Both of `CuriaOREADER' and `CuriaOWRITER' can be added to by bitwise or: `CuriaONOLCK', which means it opens a database directory without file locking, or `CuriaOLCKNB', which means locking is performed without blocking. `CuriaOCREAT' can be added to by bitwise or: `CuriaOSPARSE', which means it creates database files as sparse files.
bnum the number of elements of each bucket array. If it is not more than 0, the default value is specified. The size of each bucket array is determined on creating, and can not be changed except for by optimization of the database. Suggested size of each bucket array is about from 0.5 to 4 times of the number of all records to store.
dnum the number of division of the database. If it is not more than 0, the default value is specified. The number of division can not be changed from the initial value. The max number of division is 512.
Note:
While connecting as a writer, an exclusive lock is invoked to the database directory. While connecting as a reader, a shared lock is invoked to the database directory. The thread blocks until the lock is achieved. If `CuriaONOLCK' is used, the application is responsible for exclusion control.
virtual qdbm::Curia::~Curia (  )  throw () [virtual]

Release the resources.

Note:
If the database handle is not closed yet, it is closed.

Member Function Documentation

virtual int qdbm::Curia::bnum (  )  throw (Curia_error) [virtual]

Get the total number of the elements of each bucket array.

Returns:
the total number of the elements of each bucket array.
Exceptions:
Curia_error if an error occurs.
virtual int qdbm::Curia::busenum (  )  throw (Curia_error) [virtual]

Get the total number of the used elements of each bucket array.

Returns:
the total number of the used elements of each bucket array.
Exceptions:
Curia_error if an error occurs.
Note:
This function is inefficient because it accesses all elements of each bucket array.
virtual void qdbm::Curia::close (  )  throw (Curia_error) [virtual]

Close the database handle.

Exceptions:
Curia_error if an error occurs.
Note:
Updating a database is assured to be written when the handle is closed. If a writer opens a database but does not close it appropriately, the database will be broken.

Implements qdbm::ADBM.

virtual void qdbm::Curia::deleterec ( const Datum key  )  throw (Curia_error) [virtual]

Delete a record.

Parameters:
key reference to a key object.
Exceptions:
Curia_error if an error occurs or no record corresponds.

Implements qdbm::ADBM.

virtual bool qdbm::Curia::error (  )  throw (Curia_error) [virtual]

Check whether a fatal error occured or not.

Returns:
true if the database has a fatal error, false if not.
Exceptions:
Curia_error if an error occurs.

Implements qdbm::ADBM.

virtual bool qdbm::Curia::fatalerror (  )  throw (Curia_error) [virtual]

Check whether the database has a fatal error or not.

Returns:
true if the database has a fatal error, false if not.
Exceptions:
Curia_error if an error occurs.
virtual Datum qdbm::Curia::fetchrec ( const Datum key  )  throw (Curia_error) [virtual]

Fetch a record.

Parameters:
key reference to a key object.
Returns:
a temporary instance of the value of the corresponding record.
Exceptions:
Curia_error if an error occurs or no record corresponds.

Implements qdbm::ADBM.

virtual Datum qdbm::Curia::firstkey (  )  throw (Curia_error) [virtual]

Get the first key.

Returns:
a temporary instance of the key of the first record.
Exceptions:
Curia_error if an error occurs or no record corresponds.

Implements qdbm::ADBM.

virtual int qdbm::Curia::fsiz (  )  throw (Curia_error) [virtual]

Get the total size of database files.

Returns:
the total size of the database files.
Exceptions:
Curia_error if an error occurs.
Note:
If the total size is more than 2GB, the return value overflows.
virtual double qdbm::Curia::fsizd (  )  throw (Curia_error) [virtual]

Get the total size of database files as double-precision floating-point number.

Returns:
the total size of the database files.
Exceptions:
Curia_error if an error occurs.
virtual char* qdbm::Curia::get ( const char *  kbuf,
int  ksiz,
int  start = 0,
int  max = -1,
int *  sp = 0 
) throw (Curia_error) [virtual]

Retrieve a record.

Parameters:
kbuf the pointer to the region of a key.
ksiz the size of the region of the key. If it is negative, the size is assigned with `stdstrlen(kbuf)'.
start the offset address of the beginning of the region of the value to be read.
max the max size to read with. If it is negative, the size is unlimited.
sp the pointer to a variable to which the size of the region of the return value is assigned. If it is 0, it is not used.
Returns:
the pointer to the region of the value of the corresponding record. If the silent flag is true and no record corresponds, 0 is returned instead of exception.
Exceptions:
Curia_error if an error occurs, no record corresponds, or the size of the value of the corresponding record is less than `start'.
Note:
Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `stdmalloc' call, it should be released with the `stdfree' call if it is no longer in use.
virtual char* qdbm::Curia::getlob ( const char *  kbuf,
int  ksiz,
int  start = 0,
int  max = -1,
int *  sp = 0 
) throw (Curia_error) [virtual]

Retrieve a large object.

Parameters:
kbuf the pointer to the region of a key.
ksiz the size of the region of the key. If it is negative, the size is assigned with `stdstrlen(kbuf)'.
start the offset address of the beginning of the region of the value to be read.
max the max size to be read. If it is negative, the size to read is unlimited.
sp the pointer to a variable to which the size of the region of the return value is assigned. If it is 0, it is not used.
Returns:
the pointer to the region of the value of the corresponding large object. If the silent flag is true and no record corresponds, 0 is returned instead of exception.
Exceptions:
Curia_error if an error occurs, no record corresponds, or the size of the value of the corresponding record is less than `start'.
Note:
Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `stdmalloc' call, it should be released with the `stdfree' call if it is no longer in use.
virtual int qdbm::Curia::getlobfd ( const char *  kbuf,
int  ksiz 
) [virtual]

Get the file descriptor of a large object.

Parameters:
kbuf the pointer to the region of a key.
ksiz the size of the region of the key. If it is negative, the size is assigned with `stdstrlen(kbuf)'.
Returns:
the file descriptor of the corresponding large object. If the silent flag is true and no record corresponds, -1 is returned instead of exception.
Exceptions:
Curia_error if an error occurs or no record corresponds.
Note:
The returned file descriptor is opened with the `open' call. If the database handle was opened as a writer, the descriptor is writable (O_RDWR), else, it is not writable (O_RDONLY). The descriptor should be closed with the `close' call if it is no longer in use.
virtual int qdbm::Curia::getwb ( const char *  kbuf,
int  ksiz,
int  start,
int  max,
char *  vbuf 
) throw (Curia_error) [virtual]

Retrieve a record and write the value into a buffer.

Parameters:
kbuf the pointer to the region of a key.
ksiz the size of the region of the key. If it is negative, the size is assigned with `stdstrlen(kbuf)'.
start the offset address of the beginning of the region of the value to be read.
max the max size to be read. It shuld be equal to or less than the size of the writing buffer.
vbuf the pointer to a buffer into which the value of the corresponding record is written.
Returns:
the return value is the size of the written data. If the silent flag is true and no record corresponds, -1 is returned instead of exception.
Exceptions:
Curia_error if an error occurs, no record corresponds, or the size of the value of the corresponding record is less than `start'.
Note:
No additional zero code is appended at the end of the region of the writing buffer.
virtual int qdbm::Curia::inode (  )  throw (Curia_error) [virtual]

Get the inode number of the database directory.

Returns:
the inode number of the database directory.
Exceptions:
Curia_error if an error occurs.
virtual void qdbm::Curia::iterinit (  )  throw (Curia_error) [virtual]

Initialize the iterator of the database handle.

Exceptions:
Curia_error if an error occurs.
Note:
The iterator is used in order to access the key of every record stored in a database.
virtual char* qdbm::Curia::iternext ( int *  sp = 0  )  throw (Curia_error) [virtual]

Get the next key of the iterator.

Parameters:
sp the pointer to a variable to which the size of the region of the return value is assigned. If it is 0, it is not used.
Returns:
the pointer to the region of the next key. If the silent flag is true and no record corresponds, 0 is returned instead of exception.
Exceptions:
Curia_error if an error occurs or no record is to be get out of the iterator.
Note:
Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `stdmalloc' call, it should be released with the `stdfree' call if it is no longer in use. It is possible to access every record by iteration of calling this function. However, it is not assured if updating the database is occurred while the iteration. Besides, the order of this traversal access method is arbitrary, so it is not assured that the order of storing matches the one of the traversal access.
virtual time_t qdbm::Curia::mtime (  )  throw (Curia_error) [virtual]

Get the last modified time of the database.

Returns:
the last modified time the database.
Exceptions:
Curia_error if an error occurs.
virtual char* qdbm::Curia::name (  )  throw (Curia_error) [virtual]

Get the name of the database.

Returns:
the pointer to the region of the name of the database.
Exceptions:
Curia_error if an error occurs.
Note:
Because the region of the return value is allocated with the `stdmalloc' call, it should be released with the `stdfree' call if it is no longer in use.
virtual Datum qdbm::Curia::nextkey (  )  throw (Curia_error) [virtual]

Get the next key.

Returns:
a temporary instance of the key of the next record.
Exceptions:
Curia_error if an error occurs or no record corresponds.

Implements qdbm::ADBM.

virtual void qdbm::Curia::optimize ( int  bnum = -1  )  throw (Curia_error) [virtual]

Optimize the database.

Parameters:
bnum the number of the elements of each bucket array. If it is not more than 0, the default value is specified.
Exceptions:
Curia_error if an error occurs.
Note:
In an alternating succession of deleting and storing with overwrite or concatenate, dispensable regions accumulate. This function is useful to do away with them.
virtual bool qdbm::Curia::out ( const char *  kbuf,
int  ksiz 
) throw (Curia_error) [virtual]

Delete a record.

Parameters:
kbuf the pointer to the region of a key.
ksiz the size of the region of the key. If it is negative, the size is assigned with `stdstrlen(kbuf)'.
Returns:
always true. However, if the silent flag is true and no record corresponds, false is returned instead of exception.
Exceptions:
Curia_error if an error occurs or no record corresponds.
virtual bool qdbm::Curia::outlob ( const char *  kbuf,
int  ksiz 
) throw (Curia_error) [virtual]

Delete a large object.

Parameters:
kbuf the pointer to the region of a key.
ksiz the size of the region of the key. If it is negative, the size is assigned with `stdstrlen(kbuf)'.
Returns:
always true. However, if the silent flag is true and no record corresponds, false is returned instead of exception.
Exceptions:
Curia_error if an error occurs or no large object corresponds.
virtual bool qdbm::Curia::put ( const char *  kbuf,
int  ksiz,
const char *  vbuf,
int  vsiz,
int  dmode = Curia::DOVER 
) throw (Curia_error) [virtual]

Store a record.

Parameters:
kbuf the pointer to the region of a key.
ksiz the size of the region of the key. If it is negative, the size is assigned with `stdstrlen(kbuf)'.
vbuf the pointer to the region of a value.
vsiz the size of the region of the value. If it is negative, the size is assigned with `stdstrlen(vbuf)'.
dmode behavior when the key overlaps, by the following values: `CuriaDOVER', which means the specified value overwrites the existing one, `CuriaDKEEP', which means the existing value is kept, `CuriaDCAT', which means the specified value is concatenated at the end of the existing value.
Returns:
always true. However, if the silent flag is true and replace is cancelled, false is returned instead of exception.
Exceptions:
Curia_error if an error occurs or replace is cancelled.
virtual bool qdbm::Curia::putlob ( const char *  kbuf,
int  ksiz,
const char *  vbuf,
int  vsiz,
int  dmode = Curia::DOVER 
) throw (Curia_error) [virtual]

Store a large object.

Parameters:
kbuf the pointer to the region of a key.
ksiz the size of the region of the key. If it is negative, the size is assigned with `stdstrlen(kbuf)'.
vbuf the pointer to the region of a value.
vsiz the size of the region of the value. If it is negative, the size is assigned with `stdstrlen(vbuf)'.
dmode behavior when the key overlaps, by the following values: `CuriaDOVER', which means the specified value overwrites the existing one, `CuriaDKEEP', which means the existing value is kept, `CuriaDCAT', which means the specified value is concatenated at the end of the existing value.
Returns:
always true. However, if the silent flag is true and replace is cancelled, false is returned instead of exception.
Exceptions:
Curia_error if an error occurs or replace is cancelled.
static void qdbm::Curia::remove ( const char *  name  )  throw (Curia_error) [static]

Remove a database directory.

Parameters:
name the name of a database directory.
Exceptions:
Curia_error if an error occurs.
virtual int qdbm::Curia::rnum (  )  throw (Curia_error) [virtual]

Get the number of the records stored in the database.

Returns:
the number of the records stored in the database.
Exceptions:
Curia_error if an error occurs.
virtual int qdbm::Curia::rnumlob (  )  throw (Curia_error) [virtual]

Get the number of the large objects stored in the database.

Returns:
the number of the large objects stored in the database.
Exceptions:
Curia_error if an error occurs.
virtual void qdbm::Curia::setalign ( int  align  )  throw (Curia_error) [virtual]

Set alignment of the database handle.

Parameters:
align the basic size of alignment.
Exceptions:
Curia_error if an error occurs.
Note:
If alignment is set to a database, the efficiency of overwriting values is improved. The size of alignment is suggested to be average size of the values of the records to be stored. If alignment is positive, padding whose size is multiple number of the alignment is placed. If alignment is negative, as `vsiz' is the size of a value, the size of padding is calculated with `(vsiz / pow(2, abs(align) - 1))'. Because alignment setting is not saved in a database, you should specify alignment every opening a database.
virtual void qdbm::Curia::setfbpsiz ( int  size  )  throw (Curia_error) [virtual]

Set the size of the free block pool.

Parameters:
size the size of the free block pool of a database.
Exceptions:
Curia_error if an error occurs.
Note:
The default size of the free block pool is 16. If the size is greater, the space efficiency of overwriting values is improved with the time efficiency sacrificed.
static char* qdbm::Curia::snaffle ( const char *  name,
const char *  kbuf,
int  ksiz,
int *  sp 
) throw (Curia_error) [static]

Retrieve a record directly from a database directory.

Parameters:
name the name of a database directory.
kbuf the pointer to the region of a key.
ksiz the size of the region of the key. If it is negative, the size is assigned with `stdstrlen(kbuf)'.
sp the pointer to a variable to which the size of the region of the return value is assigned. If it is 0, it is not used.
Returns:
the pointer to the region of the value of the corresponding record.
Exceptions:
Curia_error if an error occurs or no record corresponds.
Note:
Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string. Because the region of the return value is allocated with the `stdmalloc' call, it should be released with the `stdfree' call if it is no longer in use. Although this method can be used even while the database directory is locked by another process, it is not assured that recent updated is reflected.
virtual void qdbm::Curia::storerec ( const Datum key,
const Datum val,
bool  replace = true 
) throw (Curia_error) [virtual]

Store a record.

Parameters:
key reference to a key object.
val reference to a value object.
replace whether the existing value is to be overwritten or not.
Exceptions:
Curia_error if an error occurs or replace is cancelled.

Implements qdbm::ADBM.

virtual void qdbm::Curia::sync (  )  throw (Curia_error) [virtual]

Synchronize updating contents with the files and the devices.

Note:
Curia_error if an error occurs. This function is useful when another process uses the connected database directory.
static const char* qdbm::Curia::version (  )  throw () [static]

Get the version information.

Returns:
the string of the version information.
virtual int qdbm::Curia::vsiz ( const char *  kbuf,
int  ksiz 
) throw (Curia_error) [virtual]

Get the size of the value of a record.

Parameters:
kbuf the pointer to the region of a key.
ksiz the size of the region of the key. If it is negative, the size is assigned with `stdstrlen(kbuf)'.
Returns:
the size of the value of the corresponding record. If the silent flag is true and no record corresponds, -1 is returned instead of exception.
Exceptions:
Curia_error if an error occurs or no record corresponds.
Note:
Because this function does not read the entity of a record, it is faster than `get'.
virtual int qdbm::Curia::vsizlob ( const char *  kbuf,
int  ksiz 
) throw (Curia_error) [virtual]

Get the size of the value of a large object.

Parameters:
kbuf the pointer to the region of a key.
ksiz the size of the region of the key. If it is negative, the size is assigned with `stdstrlen(kbuf)'.
Returns:
the size of the value of the corresponding large object. If the silent flag is true and no record corresponds, -1 is returned instead of exception.
Exceptions:
Curia_error if an error occurs or no large object corresponds.
Note:
Because this function does not read the entity of a large object, it is faster than `getlob'.
virtual bool qdbm::Curia::writable (  )  throw (Curia_error) [virtual]

Check whether the database handle is a writer or not.

Returns:
true if the handle is a writer, false if not.
Exceptions:
Curia_error if an error occurs.

The documentation for this class was generated from the following file:
  • xcuria.h
Generated on Thu Aug 5 02:15:30 2010 for QDBM for C++ by  doxygen 1.6.3
qdbm-1.8.78/plus/xapidoc/functions_0x6e.html0000644000175000017500000000771111426320062017720 0ustar mikiomikio QDBM for C++: Class Members
Here is a list of all documented class members with links to the class documentation for each member:

- n -

Generated on Thu Aug 5 02:15:30 2010 for QDBM for C++ by  doxygen 1.6.3
qdbm-1.8.78/plus/xapidoc/ftv2plastnode.png0000644000175000017500000000024511426320062017454 0ustar mikiomikio‰PNG  IHDRÃÃÄy PLTEÿÿÿ€€€<^»,tRNS@æØftEXtSoftwaregif2png 2.4.2£^G(IDATxÚc` 0ach(`2µ BY 1,nÁÂåíu§IEND®B`‚qdbm-1.8.78/plus/xapidoc/installdox0000755000175000017500000000502511426320062016263 0ustar mikiomikio#!/usr/bin/perl %subst = ( ); $quiet = 0; if (open(F,"search.cfg")) { $_= ; s/[ \t\n]*$//g ; $subst{"_doc"} = $_; $_= ; s/[ \t\n]*$//g ; $subst{"_cgi"} = $_; } while ( @ARGV ) { $_ = shift @ARGV; if ( s/^-// ) { if ( /^l(.*)/ ) { $v = ($1 eq "") ? shift @ARGV : $1; ($v =~ /\/$/) || ($v .= "/"); $_ = $v; if ( /(.+)\@(.+)/ ) { if ( exists $subst{$1} ) { $subst{$1} = $2; } else { print STDERR "Unknown tag file $1 given with option -l\n"; &usage(); } } else { print STDERR "Argument $_ is invalid for option -l\n"; &usage(); } } elsif ( /^q/ ) { $quiet = 1; } elsif ( /^\?|^h/ ) { &usage(); } else { print STDERR "Illegal option -$_\n"; &usage(); } } else { push (@files, $_ ); } } foreach $sub (keys %subst) { if ( $subst{$sub} eq "" ) { print STDERR "No substitute given for tag file `$sub'\n"; &usage(); } elsif ( ! $quiet && $sub ne "_doc" && $sub ne "_cgi" ) { print "Substituting $subst{$sub} for each occurence of tag file $sub\n"; } } if ( ! @files ) { if (opendir(D,".")) { foreach $file ( readdir(D) ) { $match = ".html"; next if ( $file =~ /^\.\.?$/ ); ($file =~ /$match/) && (push @files, $file); ($file =~ "tree.js") && (push @files, $file); } closedir(D); } } if ( ! @files ) { print STDERR "Warning: No input files given and none found!\n"; } foreach $f (@files) { if ( ! $quiet ) { print "Editing: $f...\n"; } $oldf = $f; $f .= ".bak"; unless (rename $oldf,$f) { print STDERR "Error: cannot rename file $oldf\n"; exit 1; } if (open(F,"<$f")) { unless (open(G,">$oldf")) { print STDERR "Error: opening file $oldf for writing\n"; exit 1; } if ($oldf ne "tree.js") { while () { s/doxygen\=\"([^ \"\:\t\>\<]*)\:([^ \"\t\>\<]*)\" (href|src)=\"\2/doxygen\=\"$1:$subst{$1}\" \3=\"$subst{$1}/g; print G "$_"; } } else { while () { s/\"([^ \"\:\t\>\<]*)\:([^ \"\t\>\<]*)\", \"\2/\"$1:$subst{$1}\" ,\"$subst{$1}/g; print G "$_"; } } } else { print STDERR "Warning file $f does not exist\n"; } unlink $f; } sub usage { print STDERR "Usage: installdox [options] [html-file [html-file ...]]\n"; print STDERR "Options:\n"; print STDERR " -l tagfile\@linkName tag file + URL or directory \n"; print STDERR " -q Quiet mode\n\n"; exit 1; } qdbm-1.8.78/plus/xapidoc/tab_r.gif0000644000175000017500000000503111426320062015727 0ustar mikiomikioGIF89a,Õö÷ùñô÷öøúüýþúûüùúûøùúêïóïóöÆÕßÒÞæØâéÞçíÝæìåìñèîòô÷ùóöø³ÈÕÁÒÝËÙâÏÜäÖá薴ŹɯÂÍ»ÎÙÃÔÞÂÓÝÈ×àÌÚâÕáèÙäê×âèåìðëðó„°ÇÑÞåÜæëãëïëñôîóõ÷úûûüüÿÿÿþþþ,,ÿ@’pH,ȤrÉl:ŸÐ¨tJ­Z¯Ø¬v •h<¬pkL.›Ïè´zÍn»ßð¸|N¯Ûïø¼~ÏwVa+‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ “*)^,*ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂö)'ÆÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæÚ¥(" ðñòóôõö÷øùúûüýþÿ H° ÁƒòK"ƒRHœH±¢Å‹3jÜȱ£Ç CŠI²¤É“(Sª\éÅu&@€ Á²¦Í›8sêÜɳ§Oÿ–(±€DУH“*]Ê´©Ó§P£JJµªÕ«X³jÝʵ«×¯S84± ‰hÓª]˶­Û·pãÊK·®Ý»xóêÝË·¯ß¿€Ó} âDÌf(^̸±ãÇ#KžL¹²å˘3kÞ̹³çÏ C‹m¹ðCÄHœXͺµë×°cËžM»¶íÛ¸sëÞÍ»·ïßÀƒ N÷ÃJ” Á®¹óçУKŸN½ºõëØ³kßν»÷ïàËO¾úñ€ dÇ@€‚‚L¤"ÉÈF:ò‘Œ¤$9† (8…&ÉÉNzò“  ¥(G©FB^²!˨)WÉÊVºò•°l¤)1™ wÄò–¸Ì¥.wÊYºäƒà¥0‡IÌbó¾|ÉHpÌf:ó™Ðìe pJ±ˆ€}Ȧ6·ÉÍnzó›à §8û0Â%"¸æ8×ÉÎvºóðŒ§<ÉPÎQ`ò%×$€>÷ÉÏ~úóŸ ¨@JЂô M¨BÊІ:ô¡¨D'ZPKF Ö¼&16ÊÑŽzô£ ©HGJRb ÷Lç5ÏÁÒ–ºô¥ÿ0©LgJÓšš#(e>¯‰Óžúô§@ ªP‡JÔ¢õ¨HMªR—ÊÔ¦:õ©PªT§JÕª&5;%U·ÊÕ®zõ«` «XÇJV«ÂC§‹ÑjY×ÊÖ¶ºõ­p«\ŠU´À¦xÍ«^÷Ê×¾úõ¯ÐÀi)$‚”ô°ˆM¬bËØÆ:vˆ, ಘͬf7ËÙÎzö³  ­hGKÚÒšö´¨M­jWËÚÖºöµ°­*$ÛSPô¶¸Í­nwËÛÞúö·ÀÅm +„â¸ÈM®r—ËÜæ:÷¹ÐE®?±9ÏêZ÷ºØÍ®v¿9€î"‚ºÛ ¯xÇKÞòb—™ÑLÿ¯z×Ë^A¢·½ð¯|ç†÷Ò÷¾øÍ¯0í«ßþú÷¿¡ä/€Là»×ÀN°‚ï(à;øÁ n0„'LaýJ¸ÂÎ0{/¬á{ؘþ°ˆG|Ë“øÄ(¥‰SÌâCrÅ.ޱŒ ãÛøÆv¬1ŽwÌc6ê¸Ç@ÞñƒLd¹ÈHNñ‘“Ìd/¹ÉPÎð“£LeO¹ÊXŽp–·|â+sùËýõ2˜ÇL_1“ùÌí53š×M5³ùÍÇt3œç¼_:ÛÙÂwÎs™õÌgøÊ¹Ï€p ýÌ?úÐ/F´¢ë¼èFãÒÐŽŽt!-éJã‘Ò–Îô1­éN»‘ÓžuÿA-êP“ºÔ>5ª3­êUWºÕ®Ž4¬cÝèYÓZѶ¾õ¡s­ëAóº×€þ5°ù,ìaç¹ØÆ¶3²“=çe3ûÍÎ~öš£-í3S»Úc¾6¶¿¬ímo¹ÛÞÆ2¸ÃMåq“Êæ>7“Ó­n$³»ÝD~7¼,ïyó¸ÞöÆ1¾ómã}óÛÈÿvµ¿Þâ\É/µÁNâ…3ÜÉ÷´Ã#Þá‰S\ÊguÆ-mñO¸ã0ÈC¾à‘“\Ë'_´ÉS^à•³|À.ùc.ó0לÐ4¿9~s®ó=÷¼Ï<ÿy|ƒ.ô4]ÏD?ºz“®ô67]ÙO§3Ó£ÞÌ©SÄW‡vÖÙl>õ­3Úëdî:Øu)ö±?ÚìÙF;˜Ë®öW²½í­|;ÜW)÷¹²îvtÞ˽w¾÷Ý|à×=xÂÞÝA;qdbm-1.8.78/plus/xapidoc/tabs.css0000644000175000017500000000346411426320062015624 0ustar mikiomikio/* tabs styles, based on http://www.alistapart.com/articles/slidingdoors */ DIV.tabs { float : left; width : 100%; background : url("tab_b.gif") repeat-x bottom; margin-bottom : 4px; } DIV.tabs UL { margin : 0px; padding-left : 10px; list-style : none; } DIV.tabs LI, DIV.tabs FORM { display : inline; margin : 0px; padding : 0px; } DIV.tabs FORM { float : right; } DIV.tabs A { float : left; background : url("tab_r.gif") no-repeat right top; border-bottom : 1px solid #84B0C7; font-size : 80%; font-weight : bold; text-decoration : none; } DIV.tabs A:hover { background-position: 100% -150px; } DIV.tabs A:link, DIV.tabs A:visited, DIV.tabs A:active, DIV.tabs A:hover { color: #1A419D; } DIV.tabs SPAN { float : left; display : block; background : url("tab_l.gif") no-repeat left top; padding : 5px 9px; white-space : nowrap; } DIV.tabs #MSearchBox { float : right; display : inline; font-size : 1em; } DIV.tabs TD { font-size : 80%; font-weight : bold; text-decoration : none; } /* Commented Backslash Hack hides rule from IE5-Mac \*/ DIV.tabs SPAN {float : none;} /* End IE5-Mac hack */ DIV.tabs A:hover SPAN { background-position: 0% -150px; } DIV.tabs LI.current A { background-position: 100% -150px; border-width : 0px; } DIV.tabs LI.current SPAN { background-position: 0% -150px; padding-bottom : 6px; } DIV.navpath { background : none; border : none; border-bottom : 1px solid #84B0C7; text-align : center; margin : 2px; padding : 2px; } qdbm-1.8.78/plus/xapidoc/classqdbm_1_1Villa__error-members.html0000644000175000017500000001275411426320062023452 0ustar mikiomikio QDBM for C++: Member List

qdbm::Villa_error Member List

This is the complete list of members for qdbm::Villa_error, including all inherited members.
code() const qdbm::Villa_error [virtual]
DBM_error()qdbm::DBM_error
DBM_error(const char *message)qdbm::DBM_error
message() const qdbm::Villa_error [virtual]
operator const char *() const qdbm::Villa_error [virtual]
operator!=(const Villa_error &ve) const qdbm::Villa_error [virtual]
operator!=(int ecode) const qdbm::Villa_error [virtual]
operator=(const Villa_error &ve)qdbm::Villa_error
operator=(int ecode)qdbm::Villa_error
operator==(const Villa_error &ve) const qdbm::Villa_error [virtual]
operator==(int ecode) const qdbm::Villa_error [virtual]
Villa_error()qdbm::Villa_error
Villa_error(int ecode)qdbm::Villa_error
Villa_error(const Villa_error &ve)qdbm::Villa_error
~DBM_error()qdbm::DBM_error [virtual]
~Villa_error()qdbm::Villa_error [virtual]
Generated on Thu Aug 5 02:15:30 2010 for QDBM for C++ by  doxygen 1.6.3
qdbm-1.8.78/plus/xapidoc/classqdbm_1_1ADBM-members.html0000644000175000017500000000662711426320062021540 0ustar mikiomikio QDBM for C++: Member List

qdbm::ADBM Member List

This is the complete list of members for qdbm::ADBM, including all inherited members.
close()=0qdbm::ADBM [pure virtual]
deleterec(const Datum &key)=0qdbm::ADBM [pure virtual]
error()=0qdbm::ADBM [pure virtual]
fetchrec(const Datum &key)=0qdbm::ADBM [pure virtual]
firstkey()=0qdbm::ADBM [pure virtual]
nextkey()=0qdbm::ADBM [pure virtual]
storerec(const Datum &key, const Datum &val, bool replace=true)=0qdbm::ADBM [pure virtual]
~ADBM()qdbm::ADBM [virtual]
Generated on Thu Aug 5 02:15:30 2010 for QDBM for C++ by  doxygen 1.6.3
qdbm-1.8.78/plus/xapidoc/ftv2vertline.png0000644000175000017500000000034511426320062017314 0ustar mikiomikio‰PNG  IHDRLƒ1Ù0PLTEÿÿÿ€€€Ó tRNS@æØftEXtSoftwaregif2png 2.4.2£^G&tEXtCommentUlead GIF SmartSaver Ver 2.0io?ÍIDATxÚc`0ÀO[!¦å<è:IEND®B`‚qdbm-1.8.78/plus/xapidoc/classqdbm_1_1Depot.png0000644000175000017500000000076411426320062020274 0ustar mikiomikio‰PNG  IHDRTP°$¢åPLTEÿÿÿÿÿÀŸŸ`ÀÀÀ{ÂÿätRNSÿÿÿÿÿÿÿÕÊT2ƒIDATxíÝnà …Ï1RÞÿ‘wql0IÐÚ¶EµuHìÏ¿%·ðU|ÍÚ03›)ŸÃ,Ó™VP¦3ÚÝ£G6ÌŒ$ié"ô]”³-ÃöŽ)–û– ¤˜nW€`H#@P64cb ñ Iù»õ_þ(wT Hs'bSzbù}—5†n¦ˆö ^'±Z-¢|@’aXóHsšŸ%väh@f¨Æ&Y÷iN #ŽÆŽqaÕzG>­þuN‰¨_Ô5rœ®,£ûŠðyžÓŠT.QÖ¯âà`NÓ¼vs:œù7e›Ó:“Ï©Öç}ž>à<ý\øKuæ+:¿§¿[Ǻ =ŽÔÐãX@]}P÷7tC7tC7tC7ôñP.Xàü”6ô— ÄÀ•Z;fý ÚÙ¾Õ|ù/Èxœ4ê¯"v-íZ Ú€ñÕW¼_$­Sv=Ô·^¯}‚^ÄGPul24›|½Öôêˆ×jzßýþSçô¦û~}Ó7ÿ^õÇB÷Ñ÷¡ Öw é]3‡IEND®B`‚qdbm-1.8.78/plus/xapidoc/tab_l.gif0000644000175000017500000000130211426320062015716 0ustar mikiomikioGIF89a ,Õö÷ùñô÷öøúüýþúûüùúûøùúêïóïóöÆÕßÒÞæØâéÞçíÝæìåìñèîòô÷ùóöø³ÈÕÁÒÝËÙâÏÜäÖá薴ŹɯÂÍ»ÎÙÃÔÞÂÓÝÈ×àÌÚâÕáèÙäê×âèåìðëðó„°ÇÑÞåÜæëãëïëñôîóõ÷úûûüüÿÿÿþþþ, ,ÿ@–P±É`H$!%CqVe2X­ŠÌJ(“Ä +€˜3 2$ÀÆ ¼kvŠä-Ëçõu*…"}ã|}|~q(" $f„ 'Žl(Œ&&$r‘™ › & ! )¢¤›{¨£¥r­ª°©¯„±¯¬´¦·»º³®«§¾¶ÃÂÀ¿²¹ÇÄËÆ²ÌÉεҽͼ„ÔÈÓ×иÙÝÕÏÙÊâÜßãçæê¾äÛÅëÇíáîÖìéïøñ÷õüÑðåùü¤Pß?‚ƒœÇÛBm åAœÎáÀ†%V܈î!Çk÷Ø/áÄ;^¤¨²$Æ–#Mf)f͇(WÎL‰“æKçÒ„° ’I)L:eD ¡Cµ´x*4 U¨h  %A«£^ÁNKb¬Ùe§X±‚´k»x!ÁÖí—2tÝÖ !¯š5tÛæé—À]$¬´%ƒXíâ.i[¬]Y­•ÊfžEëõkg`µ††:zëçÒž;£}ºµj×aa‹–Mš¶é׸cçž½»vïÛºƒóî›8ðáÈ‹'?®¼9óç©G_>Ýyuè¬_ßž]zwêß­‡Ç¾º¼mîæµG~½ûôÞთ/ž>ùööÙ«Ïÿ¿ÿýÿÅà|ÖWà}v;qdbm-1.8.78/plus/xapidoc/classqdbm_1_1Datum-members.html0000644000175000017500000001522011426320062022074 0ustar mikiomikio QDBM for C++: Member List

qdbm::Datum Member List

This is the complete list of members for qdbm::Datum, including all inherited members.
Datum(const char *dptr="", int dsize=-1)qdbm::Datum
Datum(int num)qdbm::Datum
Datum(const Datum &datum)qdbm::Datum
operator const char *() const qdbm::Datum [virtual]
operator!=(const Datum &datum) const qdbm::Datum [virtual]
operator!=(const char *str) const qdbm::Datum [virtual]
operator<<(const Datum &datum)qdbm::Datum [virtual]
operator<<(const char *str)qdbm::Datum [virtual]
operator=(const Datum &datum)qdbm::Datum
operator=(const char *str)qdbm::Datum
operator==(const Datum &datum) const qdbm::Datum [virtual]
operator==(const char *str) const qdbm::Datum [virtual]
operator[](int idx) const qdbm::Datum [virtual]
ptr() const qdbm::Datum [virtual]
qdbm::Curia (defined in qdbm::Datum)qdbm::Datum [friend]
qdbm::Depot (defined in qdbm::Datum)qdbm::Datum [friend]
qdbm::operator+ (defined in qdbm::Datum)qdbm::Datum [friend]
qdbm::operator+ (defined in qdbm::Datum)qdbm::Datum [friend]
qdbm::operator+ (defined in qdbm::Datum)qdbm::Datum [friend]
qdbm::Villa (defined in qdbm::Datum)qdbm::Datum [friend]
size() const qdbm::Datum [virtual]
~Datum()qdbm::Datum [virtual]
Generated on Thu Aug 5 02:15:30 2010 for QDBM for C++ by  doxygen 1.6.3
qdbm-1.8.78/plus/xapidoc/ftv2folderopen.png0000644000175000017500000000040511426320062017616 0ustar mikiomikio‰PNG  IHDR_Tq-PLTEÿÿÿÿÿÿÿÿÀÀÀ€€€€€’2ŒåtRNS@æØftEXtSoftwaregif2png 2.4.2£^G|IDATxÚ…A‚0E_õ-SÖÆ××Ò ±Þÿ: !¢oóþÿ‹€ j<*aÅÓCiÁ´«ùp¬ƒÊ»û¤‹®&F¶LèÃú³}¨ë¥FTFN*âΕ=º°d“…› sqƒu×ò§ò ûÒëCùýò ¤)ËÚG¬DIEND®B`‚qdbm-1.8.78/plus/xapidoc/namespacemembers.html0000644000175000017500000000355211426320062020354 0ustar mikiomikio QDBM for C++: Class Members
Here is a list of all documented namespace members with links to the namespaces they belong to:
Generated on Thu Aug 5 02:15:30 2010 for QDBM for C++ by  doxygen 1.6.3
qdbm-1.8.78/plus/xapidoc/classqdbm_1_1Datum.html0000644000175000017500000006376011426320062020460 0ustar mikiomikio QDBM for C++: qdbm::Datum Class Reference

qdbm::Datum Class Reference

Datum of records for ADBM. More...

List of all members.

Public Member Functions

 Datum (const char *dptr="", int dsize=-1)
 Create an instance.
 Datum (int num)
 Create an instance.
 Datum (const Datum &datum)
 Copy constructor.
virtual ~Datum () throw ()
 Release resources of the instance.
Datumoperator= (const Datum &datum)
 Assignment operator.
Datumoperator= (const char *str)
 Assignment operator.
virtual Datumoperator<< (const Datum &datum)
 Concatenation operator.
virtual Datumoperator<< (const char *str)
 Concatenation operator.
virtual bool operator== (const Datum &datum) const
 Equality operator.
virtual bool operator!= (const Datum &datum) const
 Inequality operator.
virtual bool operator== (const char *str) const
 Equality operator.
virtual bool operator!= (const char *str) const
 Inequality operator.
virtual char & operator[] (int idx) const
 Subscripting operator.
virtual operator const char * () const
 Cast operator into pointer to char.
virtual const char * ptr () const
 Get the pointer of the region of the datum.
virtual int size () const
 Get the size of the region of the datum.

Friends

class qdbm::Depot
class qdbm::Curia
class qdbm::Villa
Datum qdbm::operator+ (const Datum &former, const Datum &latter)
Datum qdbm::operator+ (const Datum &datum, const char *str)
Datum qdbm::operator+ (const char *str, const Datum &datum)

Detailed Description

Datum of records for ADBM.


Constructor & Destructor Documentation

qdbm::Datum::Datum ( const char *  dptr = "",
int  dsize = -1 
)

Create an instance.

Parameters:
dptr the pointer to the region of data.
dsize the size of the region. If it is negative, the size is assigned with `stdstrlen(dptr)'.
qdbm::Datum::Datum ( int  num  ) 

Create an instance.

Parameters:
num an integer number.
qdbm::Datum::Datum ( const Datum datum  ) 

Copy constructor.

Parameters:
datum a source instance.

Member Function Documentation

virtual qdbm::Datum::operator const char * (  )  const [virtual]

Cast operator into pointer to char.

Returns:
the pointer of the region of the datum.
Note:
Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string.
virtual bool qdbm::Datum::operator!= ( const char *  str  )  const [virtual]

Inequality operator.

Parameters:
str a comparing string.
Returns:
true if both do not equal, else, false.
virtual bool qdbm::Datum::operator!= ( const Datum datum  )  const [virtual]

Inequality operator.

Parameters:
datum a comparing instance.
Returns:
true if both do not equal, else, false.
virtual Datum& qdbm::Datum::operator<< ( const char *  str  )  [virtual]

Concatenation operator.

Parameters:
str a latter string.
Returns:
reference to itself.
virtual Datum& qdbm::Datum::operator<< ( const Datum datum  )  [virtual]

Concatenation operator.

Parameters:
datum a latter instance.
Returns:
reference to itself.
Datum& qdbm::Datum::operator= ( const char *  str  ) 

Assignment operator.

Parameters:
str a source string.
Returns:
reference to itself.
Datum& qdbm::Datum::operator= ( const Datum datum  ) 

Assignment operator.

Parameters:
datum a source instance.
Returns:
reference to itself.
virtual bool qdbm::Datum::operator== ( const char *  str  )  const [virtual]

Equality operator.

Parameters:
str a comparing string.
Returns:
true if both equal, else, false.
virtual bool qdbm::Datum::operator== ( const Datum datum  )  const [virtual]

Equality operator.

Parameters:
datum a comparing instance.
Returns:
true if both equal, else, false.
virtual char& qdbm::Datum::operator[] ( int  idx  )  const [virtual]

Subscripting operator.

Parameters:
idx the index of a character.
Returns:
reference of the character.
virtual const char* qdbm::Datum::ptr (  )  const [virtual]

Get the pointer of the region of the datum.

Returns:
the pointer of the region of the datum.
Note:
Because an additional zero code is appended at the end of the region of the return value, the return value can be treated as a character string.
virtual int qdbm::Datum::size (  )  const [virtual]

Get the size of the region of the datum.

Returns:
the size of the region of the datum.

The documentation for this class was generated from the following file:
  • xadbm.h
Generated on Thu Aug 5 02:15:30 2010 for QDBM for C++ by  doxygen 1.6.3
qdbm-1.8.78/plus/xapidoc/functions_0x73.html0000644000175000017500000001177211426320062017641 0ustar mikiomikio QDBM for C++: Class Members
Here is a list of all documented class members with links to the class documentation for each member:

- s -

Generated on Thu Aug 5 02:15:30 2010 for QDBM for C++ by  doxygen 1.6.3
qdbm-1.8.78/plus/xapidoc/functions.html0000644000175000017500000000706611426320062017061 0ustar mikiomikio QDBM for C++: Class Members
Here is a list of all documented class members with links to the class documentation for each member:

- b -

Generated on Thu Aug 5 02:15:30 2010 for QDBM for C++ by  doxygen 1.6.3
qdbm-1.8.78/plus/xapidoc/functions_0x69.html0000644000175000017500000000756011426320062017646 0ustar mikiomikio QDBM for C++: Class Members
Here is a list of all documented class members with links to the class documentation for each member:

- i -

Generated on Thu Aug 5 02:15:30 2010 for QDBM for C++ by  doxygen 1.6.3
qdbm-1.8.78/plus/xapidoc/functions_0x72.html0000644000175000017500000000755411426320062017643 0ustar mikiomikio QDBM for C++: Class Members
Here is a list of all documented class members with links to the class documentation for each member:

- r -

Generated on Thu Aug 5 02:15:30 2010 for QDBM for C++ by  doxygen 1.6.3
qdbm-1.8.78/plus/xapidoc/classqdbm_1_1ADBM.html0000644000175000017500000004263211426320062020104 0ustar mikiomikio QDBM for C++: qdbm::ADBM Class Reference

qdbm::ADBM Class Reference

Aabstraction for database managers compatible with DBM. More...

Inheritance diagram for qdbm::ADBM:
qdbm::Curia qdbm::Depot qdbm::Villa

List of all members.

Public Member Functions

virtual ~ADBM ()
 Release resources of the instance.
virtual void close ()=0 throw (DBM_error)
 Close the database connection.
virtual void storerec (const Datum &key, const Datum &val, bool replace=true)=0 throw (DBM_error)
 Store a record.
virtual void deleterec (const Datum &key)=0 throw (DBM_error)
 Delete a record.
virtual Datum fetchrec (const Datum &key)=0 throw (DBM_error)
 Fetch a record.
virtual Datum firstkey ()=0 throw (DBM_error)
 Get the first key.
virtual Datum nextkey ()=0 throw (DBM_error)
 Get the next key.
virtual bool error ()=0 throw (DBM_error)
 Check whether a fatal error occured or not.

Detailed Description

Aabstraction for database managers compatible with DBM.


Member Function Documentation

virtual void qdbm::ADBM::close (  )  throw (DBM_error) [pure virtual]

Close the database connection.

Exceptions:
DBM_error if an error occurs.

Implemented in qdbm::Curia, qdbm::Depot, and qdbm::Villa.

virtual void qdbm::ADBM::deleterec ( const Datum key  )  throw (DBM_error) [pure virtual]

Delete a record.

Parameters:
key reference to a key object.
Exceptions:
DBM_error if an error occurs or no record corresponds.

Implemented in qdbm::Curia, qdbm::Depot, and qdbm::Villa.

virtual bool qdbm::ADBM::error (  )  throw (DBM_error) [pure virtual]

Check whether a fatal error occured or not.

Returns:
true if the database has a fatal error, false if not.
Exceptions:
DBM_error if an error occurs.

Implemented in qdbm::Curia, qdbm::Depot, and qdbm::Villa.

virtual Datum qdbm::ADBM::fetchrec ( const Datum key  )  throw (DBM_error) [pure virtual]

Fetch a record.

Parameters:
key reference to a key object.
Returns:
a temporary instance of the value of the corresponding record.
Exceptions:
DBM_error if an error occurs or no record corresponds.

Implemented in qdbm::Curia, qdbm::Depot, and qdbm::Villa.

virtual Datum qdbm::ADBM::firstkey (  )  throw (DBM_error) [pure virtual]

Get the first key.

Returns:
a temporary instance of the key of the first record.
Exceptions:
DBM_error if an error occurs or no record corresponds.

Implemented in qdbm::Curia, qdbm::Depot, and qdbm::Villa.

virtual Datum qdbm::ADBM::nextkey (  )  throw (DBM_error) [pure virtual]

Get the next key.

Returns:
a temporary instance of the key of the next record.
Exceptions:
DBM_error if an error occurs or no record corresponds.

Implemented in qdbm::Curia, qdbm::Depot, and qdbm::Villa.

virtual void qdbm::ADBM::storerec ( const Datum key,
const Datum val,
bool  replace = true 
) throw (DBM_error) [pure virtual]

Store a record.

Parameters:
key reference to a key object.
val reference to a value object.
replace whether the existing value is to be overwritten or not.
Exceptions:
DBM_error if an error occurs or replace is cancelled.

Implemented in qdbm::Curia, qdbm::Depot, and qdbm::Villa.


The documentation for this class was generated from the following file:
  • xadbm.h
Generated on Thu Aug 5 02:15:30 2010 for QDBM for C++ by  doxygen 1.6.3
qdbm-1.8.78/plus/xapidoc/classqdbm_1_1Curia-members.html0000644000175000017500000004424511426320062022076 0ustar mikiomikio QDBM for C++: Member List

qdbm::Curia Member List

This is the complete list of members for qdbm::Curia, including all inherited members.
bnum()qdbm::Curia [virtual]
busenum()qdbm::Curia [virtual]
close()qdbm::Curia [virtual]
Curia(const char *name, int omode=Curia::OREADER, int bnum=-1, int dnum=-1)qdbm::Curia
DCATqdbm::Curia [static]
deleterec(const Datum &key)qdbm::Curia [virtual]
DKEEPqdbm::Curia [static]
DOVERqdbm::Curia [static]
EALLOCqdbm::Curia [static]
EBROKENqdbm::Curia [static]
ECLOSEqdbm::Curia [static]
EFATALqdbm::Curia [static]
EKEEPqdbm::Curia [static]
ELOCKqdbm::Curia [static]
EMAPqdbm::Curia [static]
EMISCqdbm::Curia [static]
EMKDIRqdbm::Curia [static]
EMODEqdbm::Curia [static]
ENOERRqdbm::Curia [static]
ENOITEMqdbm::Curia [static]
EOPENqdbm::Curia [static]
EREADqdbm::Curia [static]
ERMDIRqdbm::Curia [static]
error()qdbm::Curia [virtual]
ESEEKqdbm::Curia [static]
ESTATqdbm::Curia [static]
ESYNCqdbm::Curia [static]
ETRUNCqdbm::Curia [static]
EUNLINKqdbm::Curia [static]
EWRITEqdbm::Curia [static]
fatalerror()qdbm::Curia [virtual]
fetchrec(const Datum &key)qdbm::Curia [virtual]
firstkey()qdbm::Curia [virtual]
fsiz()qdbm::Curia [virtual]
fsizd()qdbm::Curia [virtual]
get(const char *kbuf, int ksiz, int start=0, int max=-1, int *sp=0)qdbm::Curia [virtual]
getlob(const char *kbuf, int ksiz, int start=0, int max=-1, int *sp=0)qdbm::Curia [virtual]
getlobfd(const char *kbuf, int ksiz)qdbm::Curia [virtual]
getwb(const char *kbuf, int ksiz, int start, int max, char *vbuf)qdbm::Curia [virtual]
inode()qdbm::Curia [virtual]
iterinit()qdbm::Curia [virtual]
iternext(int *sp=0)qdbm::Curia [virtual]
mtime()qdbm::Curia [virtual]
name()qdbm::Curia [virtual]
nextkey()qdbm::Curia [virtual]
OCREATqdbm::Curia [static]
OLCKNBqdbm::Curia [static]
ONOLCKqdbm::Curia [static]
optimize(int bnum=-1)qdbm::Curia [virtual]
OREADERqdbm::Curia [static]
OSPARSEqdbm::Curia [static]
OTRUNCqdbm::Curia [static]
out(const char *kbuf, int ksiz)qdbm::Curia [virtual]
outlob(const char *kbuf, int ksiz)qdbm::Curia [virtual]
OWRITERqdbm::Curia [static]
put(const char *kbuf, int ksiz, const char *vbuf, int vsiz, int dmode=Curia::DOVER)qdbm::Curia [virtual]
putlob(const char *kbuf, int ksiz, const char *vbuf, int vsiz, int dmode=Curia::DOVER)qdbm::Curia [virtual]
remove(const char *name)qdbm::Curia [static]
rnum()qdbm::Curia [virtual]
rnumlob()qdbm::Curia [virtual]
setalign(int align)qdbm::Curia [virtual]
setfbpsiz(int size)qdbm::Curia [virtual]
silentqdbm::Curia
snaffle(const char *name, const char *kbuf, int ksiz, int *sp)qdbm::Curia [static]
storerec(const Datum &key, const Datum &val, bool replace=true)qdbm::Curia [virtual]
sync()qdbm::Curia [virtual]
version()qdbm::Curia [static]
vsiz(const char *kbuf, int ksiz)qdbm::Curia [virtual]
vsizlob(const char *kbuf, int ksiz)qdbm::Curia [virtual]
writable()qdbm::Curia [virtual]
~ADBM()qdbm::ADBM [virtual]
~Curia()qdbm::Curia [virtual]
Generated on Thu Aug 5 02:15:30 2010 for QDBM for C++ by  doxygen 1.6.3
qdbm-1.8.78/plus/xapidoc/annotated.html0000644000175000017500000000741311426320062017022 0ustar mikiomikio QDBM for C++: Class List

Class List

Here are the classes, structs, unions and interfaces with brief descriptions:
qdbm::ADBMAabstraction for database managers compatible with DBM
qdbm::CuriaC++ API of Curia, the extended API of QDBM
qdbm::Curia_errorError container for Curia
qdbm::DatumDatum of records for ADBM
qdbm::DBM_errorError container for ADBM
qdbm::DepotC++ API of Depot, the basic API of QDBM
qdbm::Depot_errorError container for Depot
qdbm::VillaC++ API of Villa, the basic API of QDBM
qdbm::Villa_errorError container for Villa
Generated on Thu Aug 5 02:15:30 2010 for QDBM for C++ by  doxygen 1.6.3
qdbm-1.8.78/plus/xapidoc/functions_0x6c.html0000644000175000017500000000637711426320062017725 0ustar mikiomikio QDBM for C++: Class Members
Here is a list of all documented class members with links to the class documentation for each member:

- l -

Generated on Thu Aug 5 02:15:30 2010 for QDBM for C++ by  doxygen 1.6.3
qdbm-1.8.78/plus/xapidoc/classqdbm_1_1Depot__error-members.html0000644000175000017500000001275411426320062023456 0ustar mikiomikio QDBM for C++: Member List

qdbm::Depot_error Member List

This is the complete list of members for qdbm::Depot_error, including all inherited members.
code() const qdbm::Depot_error [virtual]
DBM_error()qdbm::DBM_error
DBM_error(const char *message)qdbm::DBM_error
Depot_error()qdbm::Depot_error
Depot_error(int ecode)qdbm::Depot_error
Depot_error(const Depot_error &de)qdbm::Depot_error
message() const qdbm::Depot_error [virtual]
operator const char *() const qdbm::Depot_error [virtual]
operator!=(const Depot_error &de) const qdbm::Depot_error [virtual]
operator!=(int ecode) const qdbm::Depot_error [virtual]
operator=(const Depot_error &de)qdbm::Depot_error
operator=(int ecode)qdbm::Depot_error
operator==(const Depot_error &de) const qdbm::Depot_error [virtual]
operator==(int ecode) const qdbm::Depot_error [virtual]
~DBM_error()qdbm::DBM_error [virtual]
~Depot_error()qdbm::Depot_error [virtual]
Generated on Thu Aug 5 02:15:30 2010 for QDBM for C++ by  doxygen 1.6.3
qdbm-1.8.78/plus/xapidoc/ftv2node.png0000644000175000017500000000035311426320062016410 0ustar mikiomikio‰PNG  IHDRLƒ1Ù0PLTEÿÿÿ€€€Ó tRNS@æØftEXtSoftwaregif2png 2.4.2£^G&tEXtCommentUlead GIF SmartSaver Ver 2.0io?ÍIDATxÚc`0ÀO ˆVŒÂ.RâúE:áIEND®B`‚qdbm-1.8.78/plus/xapidoc/hierarchy.html0000644000175000017500000000416611426320062017025 0ustar mikiomikio QDBM for C++: Hierarchical Index

Class Hierarchy

This inheritance list is sorted roughly, but not completely, alphabetically:
Generated on Thu Aug 5 02:15:30 2010 for QDBM for C++ by  doxygen 1.6.3
qdbm-1.8.78/plus/xapidoc/classqdbm_1_1Depot__error.html0000644000175000017500000004464611426320062022033 0ustar mikiomikio QDBM for C++: qdbm::Depot_error Class Reference

qdbm::Depot_error Class Reference

Error container for Depot. More...

Inheritance diagram for qdbm::Depot_error:
qdbm::DBM_error

List of all members.

Public Member Functions

 Depot_error () throw ()
 Create an instance.
 Depot_error (int ecode) throw ()
 Create an instance.
 Depot_error (const Depot_error &de) throw ()
 Copy constructor.
virtual ~Depot_error () throw ()
 Release resources of the instance.
Depot_erroroperator= (const Depot_error &de) throw ()
 Assignment operator.
Depot_erroroperator= (int ecode) throw ()
 Assignment operator.
virtual bool operator== (const Depot_error &de) const throw ()
 Equality operator.
virtual bool operator!= (const Depot_error &de) const throw ()
 Inequality operator.
virtual bool operator== (int ecode) const throw ()
 Equality operator.
virtual bool operator!= (int ecode) const throw ()
 Inequality operator.
virtual operator const char * () const throw ()
 Cast operator into pointer to char.
virtual int code () const throw ()
 Get the error code.
virtual const char * message () const throw ()
 Get the error message.

Detailed Description

Error container for Depot.


Constructor & Destructor Documentation

qdbm::Depot_error::Depot_error ( int  ecode  )  throw ()

Create an instance.

Parameters:
ecode the error code.
qdbm::Depot_error::Depot_error ( const Depot_error de  )  throw ()

Copy constructor.

Parameters:
de a source instance.

Member Function Documentation

virtual int qdbm::Depot_error::code (  )  const throw () [virtual]

Get the error code.

Returns:
the error code.
virtual const char* qdbm::Depot_error::message (  )  const throw () [virtual]

Get the error message.

Returns:
the pointer to the string.

Reimplemented from qdbm::DBM_error.

virtual qdbm::Depot_error::operator const char * (  )  const throw () [virtual]

Cast operator into pointer to char.

Returns:
the pointer to the string.

Reimplemented from qdbm::DBM_error.

virtual bool qdbm::Depot_error::operator!= ( int  ecode  )  const throw () [virtual]

Inequality operator.

Parameters:
ecode a comparing error code.
Returns:
true if both do not equal, else, false.
virtual bool qdbm::Depot_error::operator!= ( const Depot_error de  )  const throw () [virtual]

Inequality operator.

Parameters:
de a comparing instance.
Returns:
true if both do not equal, else, false.
Depot_error& qdbm::Depot_error::operator= ( int  ecode  )  throw ()

Assignment operator.

Parameters:
ecode the error code.
Returns:
reference to itself.
Depot_error& qdbm::Depot_error::operator= ( const Depot_error de  )  throw ()

Assignment operator.

Parameters:
de a source instance.
Returns:
reference to itself.
virtual bool qdbm::Depot_error::operator== ( int  ecode  )  const throw () [virtual]

Equality operator.

Parameters:
ecode a comparing error code.
Returns:
true if both equal, else, false.
virtual bool qdbm::Depot_error::operator== ( const Depot_error de  )  const throw () [virtual]

Equality operator.

Parameters:
de a comparing instance.
Returns:
true if both equal, else, false.

The documentation for this class was generated from the following file:
  • xdepot.h
Generated on Thu Aug 5 02:15:30 2010 for QDBM for C++ by  doxygen 1.6.3
qdbm-1.8.78/plus/xapidoc/functions_0x6d.html0000644000175000017500000000761211426320062017717 0ustar mikiomikio QDBM for C++: Class Members
Here is a list of all documented class members with links to the class documentation for each member:

- m -

Generated on Thu Aug 5 02:15:30 2010 for QDBM for C++ by  doxygen 1.6.3
qdbm-1.8.78/plus/xapidoc/classqdbm_1_1Curia.png0000644000175000017500000000076511426320062020265 0ustar mikiomikio‰PNG  IHDRTP°$¢åPLTEÿÿÿÿÿÀŸŸ`ÀÀÀ{ÂÿätRNSÿÿÿÿÿÿÿÕÊT2„IDATxíÛŽÃ Dç)ÿÿÉû`œK»ª–ìn$Z7`Ž/LÉ«b´³ž%™™Í´Ïa¶éLkjÓ™ÝÍaÆ«=Hf€•é¶©÷’{¯˜ÎŠØî‡ œûš”,„†„ð=˜QØÍ|%Òâ1=Îßãááð€Egã~Ίù°=‡¦ÐXSôÉY£Ù¾ÈKÈ½Ž¢ÓºVØY£I•á½0†¥?"™Ç`g:±z¿³žÑÿ®S”ý˾fíYÓ™eD¬LŸ£N;Òkɶ–|=^è´èu§Ó—šÿÐvýM¾§Æ9¯ûô÷éÏmS¼Tg¾¢ë{ú»±}àû§Ðm»ztÛn Þ}Ðé/è‚.è‚.è‚.èã¡Ü0Äü’ô· èe,à¸trýÊ%åÔß‚\.ý—¯ù:^À5tóã ®øó´O#âv· Ö!Ó>9º;¿IзåŸ{zBž~x|½>ý:댫¨”_ËØ‹nÊÿë¹Ðuõý_è ã C ÒsøH‰IEND®B`‚qdbm-1.8.78/plus/xapidoc/functions_0x7e.html0000644000175000017500000001034711426320062017720 0ustar mikiomikio QDBM for C++: Class Members
Here is a list of all documented class members with links to the class documentation for each member:

- ~ -

Generated on Thu Aug 5 02:15:30 2010 for QDBM for C++ by  doxygen 1.6.3
qdbm-1.8.78/plus/xapidoc/main.html0000644000175000017500000000544411426320062015773 0ustar mikiomikio QDBM for C++: Main Page

QDBM for C++ Documentation

QDBM is a library of routines for managing a database. The database is a simple data file containing records, each is a pair of a key and a value. Every key and value is serial bytes with variable length. Both binary data and character string can be used as a key and a value. There is neither concept of data tables nor data types. Records are organazed in hash table or B+ tree.

As for database of hash table, each key must be unique within a database, so it is impossible to store two or more records with a key overlaps. The following access methods are provided to the database: storing a record with a key and a value, deleting a record by a key, retrieving a record by a key. Moreover, traversal access to every key are provided, although the order is arbitrary. These access methods are similar to ones of DBM (or its followers, NDBM and GDBM) library defined in the UNIX standard. QDBM is an alternative for DBM because of its higher performance.

As for database of B+ tree, records whose keys are duplicated can be stored. Access methods of storing, deleting and retrieving are provided as with the database of hash table. Records are stored in order by a comparing function assigned by a user. It is possible to access each record with the cursor in ascending or descending order. According to this mechanism, forward matching search for strings and range search for integers are realized. Moreover, transaction is available in database of B+ tree.

QDBM provides API for C++. This encapsulates the basic API and the extended API of QDBM, and make them thread-safe. Each class is packaged in the namespace `qdbm'.

Refer to `http://fallabs.com/qdbm/' for more information.

Generated on Thu Aug 5 02:15:30 2010 for QDBM for C++ by  doxygen 1.6.3
qdbm-1.8.78/plus/xapidoc/ftv2lastnode.png0000644000175000017500000000035111426320062017272 0ustar mikiomikio‰PNG  IHDRLƒ1Ù0PLTEÿÿÿ€€€Ó tRNS@æØftEXtSoftwaregif2png 2.4.2£^G&tEXtCommentUlead GIF SmartSaver Ver 2.0io?ÍIDATxÚc`0ÀO È3$§ˆÊ3=IEND®B`‚qdbm-1.8.78/plus/xapidoc/ftv2mnode.png0000644000175000017500000000030211426320062016557 0ustar mikiomikio‰PNG  IHDRLƒ1Ù$PLTEÀÀÀ€€€S¾™tRNS@æØftEXtSoftwaregif2png 2.4.2£^G*IDATxÚc` .àBt§RT÷n €ñÁbÜLJJÜÜÜÈ"05˜ÚÑ·y'ª÷–IEND®B`‚qdbm-1.8.78/plus/xapidoc/functions_0x77.html0000644000175000017500000000670511426320062017645 0ustar mikiomikio QDBM for C++: Class Members
Here is a list of all documented class members with links to the class documentation for each member:

- w -

Generated on Thu Aug 5 02:15:30 2010 for QDBM for C++ by  doxygen 1.6.3
qdbm-1.8.78/plus/xapidoc/classqdbm_1_1Depot__error.png0000644000175000017500000000113511426320062021635 0ustar mikiomikio‰PNG  IHDRtPÿy¡5PLTEÿÿÿÿÿÀŸŸ`ÀÀÀ{ÂÿätRNSÿÿÿÿÿÿÿÕÊT2ìIDATxí]rƒ0 „wåîä>h%d0mC˜Lìi1þÓ'‰Uü µ¦vÕ€™Ù•ý÷0ÛåLkh—3ݬàð IÒÌ PëÑÿÝжÏ0£É'ô}ûxÔ7 Äú ‘h4cžqÛáS@“ ÀŒ$£ç‹š0ŸØé×mÐý& š ±—¿È7“í`Ê7÷Y.ÓCÔ Ã?0ÏV–û<ÝÿØÏªgÄþ:±¯SfVÿoÄá¶åS®Ç¸Óšr±tZ+uê[µge{¼kîÒ§\q§ãNs©½]†ˆü{ÖÜf]Ίo­U}w)Ô©tºSNj¼Ã:Ý䎌܇oL_ÇuúX½íkö9x°§·3÷LÉÁ¼Oç}úì}ú)Ëjñß9ÎÉmyâìGA—åêÐe¹z ô‹Ô;¡:¡:¡:¡:¡úAPÞÐÀëS4¡_%qá[zôWÛ§ ^=z‚ŒÅÕ˜¿Ñcöe÷ƒŒ©LIÚ–Õu¢BW`üûD€¯—²k›MÈñu‡|ì¡tvªµt×m ÛA&õÔu•à^ í"FÚ ï7èþ› ÅÀŸßôOèX½ý_Öé@½©’ªÞ|”‰m>øãtú·ì•и,/…Î[fB/‡ÞÐ~0${àNí¯IEND®B`‚qdbm-1.8.78/plus/xapidoc/classqdbm_1_1DBM__error.png0000644000175000017500000000137311426320062021170 0ustar mikiomikio‰PNG  IHDRpP7ÞPLTEÿÿÿÿÿÀŸŸ`ÀÀÀ{ÂÿätRNSÿÿÿÿÿÿÿÕÊT2ŠIDATxíÝÛ’« †Ñ´©Êû?ò¾€–n9”Ñ=á£jr@Æß^iñöõìÆÃ%? ¾D$à€8à€§z©™ˆˆˆý ËÆï×ýøõ ð±êE¢¡¼^ãg¿V§Êàzijø ÀMõ [ÿ„¢ïô<ö»ÿMDƒx–4¸ßÍ›mñ¾ïáUðü‹½ Oïù®c§€ß^z¾Þ½‡Àmÿ5ÙRºÁwèÛ¼ÉÍÖí6Ž\3®H/fð¬ú{(¿€Bœÿ¯Á6pÀpÀ¯¨þ±4øüø@øO{ü·½œ‡&pÀ€ÎpÀ€þ·J^y¬×c ¦NÉ€“NÉ€“NÉ€“8%N:%N:%þ[éïéñ™þÏ¥ÓßÛíÖ¼^:à€8à¿.Û&•å"’ª-,¹.…ì©«hׯÀ>1º\&…/?;ü¼)»ÁE6Ù_7‘mÛâçCUáX8.¡û|/†EáD~¢RroxJ‹«Â7{­ø xû LÙz`°pžÒô/LhªÍÞ“Môñ²ÌŠ4Q.¹;<ÎgÄ—Á;®à>Zx®ýZ8m­Ã÷ÉBnee¼/ÜŸ‚×â«à­+(tø`á—»ç™>ݾÎ_oÅσëÞà¶”‘¯?ÞYî)÷…?dÄ_>Zx{/³ïo'àÞ ÏO×ÜÇÁ›åû_}¢p^~Lg¹z …UvKñ7µr•’ÛázÃêéâ*ýÖ_ï*?-܃gG¾8ê7õÀ˜¾Ö øMå_.a<Þ9xátøÓ~Ó¨—¼B:à€8àüaJ^.ýšÈK~¿·eÿIEND®B`‚qdbm-1.8.78/plus/xapidoc/functions_func.html0000644000175000017500000005264511426320062020077 0ustar mikiomikio QDBM for C++: Class Members - Functions
 

- b -

- c -

- d -

- e -

- f -

- g -

- i -

- l -

- m -

- n -

- o -

- p -

- r -

- s -

- t -

- v -

- w -

- ~ -

Generated on Thu Aug 5 02:15:30 2010 for QDBM for C++ by  doxygen 1.6.3
qdbm-1.8.78/plus/xapidoc/classqdbm_1_1Curia__error.png0000644000175000017500000000112611426320062021625 0ustar mikiomikio‰PNG  IHDRrPògÑrPLTEÿÿÿÿÿÀŸŸ`ÀÀÀ{ÂÿätRNSÿÿÿÿÿÿÿÕÊT2åIDATxí]ŽÃ „gŒ”ûyüƒ!dÕT-ÕnÔÒ€ñ7vìò ÍÆ®gˆˆìœ¿ØvÚþÛi‡.O$%ý íûü¹¡=\ž ¡˜" ¨v\+¼˜Ðc!¤ TžPÏ®ˆ€Æìd’@ÍÅ„á§÷¥z j¦¢Hbd‹ ÐìªcóìDS¦Š)¢ÊÕëÜ%tm`œÌ$ HÕîöÌu ·W³œ«Þ—Œè»6Cº¥z6E±ïÏC…YvGäÜ—ªÍ‘A6dd-ž?µ;TZTÜÔ—úý=æ¬F C¶’²©ÂrMG–{…¥¾´ZõZ3W9Öe_NY#=뮌¡tÕ—·úëÙ9õåýÝ™:±ïË}Ý—u_>y_¾ynhú>› +á7>ÇÒýq<ôï c;s?ò8¶3?€ü’Š-d! YÈB²…,d!?‰äöîÎN!ÿ5’¸”ArÞº¯ø’Ï1.‘Ú/ö Ò7;"~éžîSƒSžÍg_ÈÈŽó.86ÃÙ×Ga¾é}aBºæ°Z¦(cq¼°| r¨*ýO{3òœØ¡Ö~CžßåT¾îÅ,®‘E¹®Ø ì´Û %63½@ã+-Ì}¹çèuH¿ 7"ë&)ä&äöñ³A TreeView
 
qdbm-1.8.78/plus/xapidoc/ftv2folderclosed.png0000644000175000017500000000040311426320062020124 0ustar mikiomikio‰PNG  IHDR_Tq-PLTEÿÿÿÿÿÿÀÀÀ€€€€€Bî@átRNS@æØftEXtSoftwaregif2png 2.4.2£^G}IDATxÚŽÁ „0C#ŒwûB½+øemï¢ÍÿÿŠ3­îZö°Úð†¦ˆ@S‚š×QB%®zv íêyyIsáò2_I¹í#` Í6fä@K´ÛÛåîx ù–m‹¢nùPd¦p¶P Óx†˜¦Þ]%Íþ߯ ˜`½ IEND®B`‚qdbm-1.8.78/plus/Makefile.in0000644000175000017500000001754710573423442014616 0ustar mikiomikio# Makefile for C++ interface of QDBM #================================================================ # Setting variables #================================================================ # Generic settings SHELL = @SHELL@ srcdir = @srcdir@ VPATH = @srcdir@ # Packaging PACKAGE = qdbm LIBVER = @LIBVER@ LIBREV = @LIBREV@ # Targets MYHEADS = xqdbm.h xadbm.h xdepot.h xcuria.h xvilla.h MYLIBOBJS = xqdbm.o xadbm.o xdepot.o xcuria.o xvilla.o MYLIBS = libxqdbm.a libxqdbm.so.$(LIBVER).$(LIBREV).0 libxqdbm.so.$(LIBVER) libxqdbm.so MYBINS = xdptest xcrtest xvltest MYDOCS = xspex.html xspex-ja.html xapidoc MYWINLIBS = libxqdbm.a libxqdbm.dll.a MYMACLIBS = libxqdbm.a libxqdbm.$(LIBVER).$(LIBREV).0.dylib \ libxqdbm.$(LIBVER).dylib libxqdbm.dylib MYHPUXLIBS = libxqdbm.a libxqdbm.sl # Install destinations prefix = @prefix@ exec_prefix = @exec_prefix@ MYHEADDIR = @includedir@ MYLIBDIR = @libdir@ MYBINDIR = @bindir@ MYDATADIR = @datadir@/$(PACKAGE)/plus DESTDIR = # Building binaries CXX = @CXX@ CPPFLAGS = @CPPFLAGS@ -I$(srcdir) -I$(srcdir)/.. -I$(MYHEADDIR) \ -I$(HOME)/include -I/usr/local/include @MYDEFS@ \ -D_XOPEN_SOURCE_EXTENDED=1 -D_GNU_SOURCE=1 -D__EXTENSIONS__=1 -D_HPUX_SOURCE=1 \ -D_POSIX_MAPPED_FILES=1 -D_POSIX_SYNCHRONIZED_IO=1 \ -DPIC=1 -D_THREAD_SAFE=1 -D_REENTRANT=1 -DNDEBUG CXXFLAGS = -Wall -ansi -pedantic -fsigned-char -fPIC -O2 -fno-strict-aliasing @MYOPTS@ LD = @LD@ LIBS = -lqdbm @LIBS@ LIBLDFLAGS = @LDFLAGS@ -L. -L$(srcdir)/.. -L$(MYLIBDIR) \ -L$(HOME)/lib -L/usr/local/lib $(LIBS) LDFLAGS = @LDFLAGS@ -L. -L$(srcdir)/.. -L$(MYLIBDIR) \ -L$(HOME)/lib -L/usr/local/lib -lxqdbm $(LIBS) LDENV = LD_RUN_PATH=/lib:/usr/lib:$(MYLIBDIR):$(HOME)/lib:/usr/local/lib AR = @AR@ ARFLAGS = rcsv RUNENV = LD_LIBRARY_PATH=.:..:/lib:/usr/lib:$(MYLIBDIR):$(HOME)/lib:/usr/local/lib #================================================================ # Suffix rules #================================================================ .SUFFIXES : .SUFFIXES : .cc .o .cc.o : $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $< #================================================================ # Actions #================================================================ targets : @TARGETS@ all : $(MYLIBS) $(MYBINS) @printf '\n' @printf '#================================================================\n' @printf '# Ready to install.\n' @printf '#================================================================\n' static : make MYLIBS="$(MYLIBS)" LDFLAGS="-static $(LDFLAGS)" all debug : make MYLIBS="$(MYLIBS)" CPPFLAGS="$(CPPFLAGS) -UNDEBUG" \ CXXFLAGS="$(CXXFLAGS) -g" LDFLAGS="-static $(LDFLAGS)" all devel : make MYLIBS="$(MYLIBS)" CPPFLAGS="$(CPPFLAGS) -UNDEBUG" \ CXXFLAGS="$(CXXFLAGS) -g -pipe" all sync ; sync profile : make MYLIBS="$(MYLIBS)" CXXFLAGS="$(CXXFLAGS) -pg -g -Werror" \ LDFLAGS="-static $(LDFLAGS)" all clean : rm -rf $(MYLIBS) $(MYBINS) *.o *.a *.so \ *.exe *.dll.a *.dll *.dylib *.sl a.out TAGS gmon.out leak.log casket *~ install : mkdir -p $(DESTDIR)$(MYHEADDIR) cd $(srcdir) && cp -Rf $(MYHEADS) $(DESTDIR)$(MYHEADDIR) mkdir -p $(DESTDIR)$(MYLIBDIR) cp -Rf $(MYLIBS) $(DESTDIR)$(MYLIBDIR) mkdir -p $(DESTDIR)$(MYBINDIR) cp -Rf $(MYBINS) $(DESTDIR)$(MYBINDIR) mkdir -p $(DESTDIR)$(MYDATADIR) cp -Rf $(MYDOCS) $(DESTDIR)$(MYDATADIR) @printf '\n' @printf '#================================================================\n' @printf '# Thanks for using QDBM for C++.\n' @printf '#================================================================\n' install-strip : make DESTDIR=$(DESTDIR) install cd $(DESTDIR)$(MYBINDIR) && strip $(MYBINS) uninstall : cd $(DESTDIR)$(MYHEADDIR) && rm -f $(MYHEADS) cd $(DESTDIR)$(MYLIBDIR) && rm -f $(MYLIBS) cd $(DESTDIR)$(MYBINDIR) && rm -f $(MYBINS) rm -rf $(DESTDIR)$(MYDATADIR) dist : autoconf make doc make distclean distclean : clean rm -rf Makefile config.cache config.log config.status autom4te.cache TAGS : etags -o $@ *.c *.h check : sync ; sync rm -rf casket* $(RUNENV) ./xdptest write casket 50000 5000 $(RUNENV) ./xdptest read casket $(RUNENV) ./xdptest multi casket 10000 1000 10 $(RUNENV) ./xdptest misc casket rm -rf casket* $(RUNENV) ./xcrtest write casket 50000 5000 10 $(RUNENV) ./xcrtest read casket $(RUNENV) ./xcrtest multi casket 10000 1000 10 10 $(RUNENV) ./xcrtest misc casket rm -rf casket* $(RUNENV) ./xcrtest write -lob casket 500 50 10 $(RUNENV) ./xcrtest read -lob casket $(RUNENV) ./xcrtest multi -lob casket 500 50 10 10 rm -rf casket* $(RUNENV) ./xvltest write casket 50000 $(RUNENV) ./xvltest read casket $(RUNENV) ./xvltest multi casket 10000 10 $(RUNENV) ./xvltest misc casket rm -rf casket* @printf '\n' @printf '#================================================================\n' @printf '# Checking completed.\n' @printf '#================================================================\n' doc : make docclean mkdir -p xapidoc doxygen docclean : rm -rf xapidoc win : make MYLIBS="libxqdbm.dll.a" \ CXXFLAGS="-Wall -ansi -pedantic -fsigned-char -O0 -DNDEBUG" check-win : make check install-win : make MYBINS="`for file in $(MYBINS) ; do echo $$file.exe ; done | tr '\n' ' '`" \ MYLIBS="libxqdbm.dll.a" install cp -Rf xqdbm.dll $(DESTDIR)$(MYBINDIR) uninstall-win : make MYBINS="`for file in $(MYBINS) ; do echo $$file.exe ; done | tr '\n' ' '`" \ MYLIBS="libxqdbm.dll.a" uninstall rm -f $(DESTDIR)$(MYBINDIR)/xqdbm.dll mac : make MYLIBS="$(MYMACLIBS)" CXXFLAGS="-Wall -fsigned-char -fno-common -O1 -DNDEBUG" check-mac : make RUNENV="DYLD_LIBRARY_PATH=.:..:/usr/local/lib" check install-mac : make MYLIBS="$(MYMACLIBS)" install uninstall-mac : make MYLIBS="$(MYMACLIBS)" uninstall hpux : make MYLIBS="$(MYHPUXLIBS)" check-hpux : make RUNENV="SHLIB_PATH=.:..:/usr/local/lib" check install-hpux : make MYLIBS="$(MYHPUXLIBS)" install uninstall-hpux : make MYLIBS="$(MYHPUXLIBS)" uninstall .PHONY : all clean install check #================================================================ # Building binaries #================================================================ libxqdbm.a : $(MYLIBOBJS) $(AR) $(ARFLAGS) $@ $(MYLIBOBJS) libxqdbm.so.$(LIBVER).$(LIBREV).0 : $(MYLIBOBJS) if $(CXX) --print-prog-name=ld | egrep -i '(solaris|/ccs/|/ucb/)' > /dev/null ; \ then \ $(CXX) -shared -Wl,-G,-h,libxqdbm.so.$(LIBVER) -o $@ $(MYLIBOBJS) $(LIBLDFLAGS) ; \ else \ $(CXX) -shared -Wl,-soname,libxqdbm.so.$(LIBVER) -o $@ $(MYLIBOBJS) $(LIBLDFLAGS) ; \ fi libxqdbm.so.$(LIBVER) : libxqdbm.so.$(LIBVER).$(LIBREV).0 ln -f -s libxqdbm.so.$(LIBVER).$(LIBREV).0 $@ libxqdbm.so : libxqdbm.so.$(LIBVER).$(LIBREV).0 ln -f -s libxqdbm.so.$(LIBVER).$(LIBREV).0 $@ libxqdbm.dll.a : xqdbm.dll xqdbm.dll : $(MYLIBOBJS) $(CXX) -shared -o $@ \ -Wl,--out-implib=lib$@.a \ -Wl,--export-all-symbols \ -Wl,--enable-auto-import \ -Wl,--add-stdcall-alias \ -Wl,--whole-archive \ -Wl,--no-whole-archive $(MYLIBOBJS) $(LIBLDFLAGS) libxqdbm.$(LIBVER).$(LIBREV).0.dylib : $(MYLIBOBJS) $(CXX) -dynamiclib -o $@ \ -install_name $(MYLIBDIR)/libxqdbm.$(LIBVER).dylib \ -current_version $(LIBVER).$(LIBREV).0 \ -compatibility_version $(LIBVER) \ $(MYLIBOBJS) $(LIBLDFLAGS) libxqdbm.$(LIBVER).dylib : libxqdbm.$(LIBVER).$(LIBREV).0.dylib ln -f -s libxqdbm.$(LIBVER).$(LIBREV).0.dylib $@ libxqdbm.dylib : libxqdbm.$(LIBVER).$(LIBREV).0.dylib ln -f -s libxqdbm.$(LIBVER).$(LIBREV).0.dylib $@ libxqdbm.sl : $(MYLIBOBJS) $(CXX) -shared -Wl,-b -o $@ $(MYLIBOBJS) $(LIBLDFLAGS) xdptest : xdptest.o $(MYLIBS) $(LDENV) $(CXX) $(CXXFLAGS) -o $@ xdptest.o $(LDFLAGS) xcrtest : xcrtest.o $(MYLIBS) $(LDENV) $(CXX) $(CXXFLAGS) -o $@ xcrtest.o $(LDFLAGS) xvltest : xvltest.o $(MYLIBS) $(LDENV) $(CXX) $(CXXFLAGS) -o $@ xvltest.o $(LDFLAGS) xadbm.o : xqdbm.h xadbm.h xdepot.o xdptest.o : xqdbm.h xadbm.h xdepot.h xcuria.o xcrtest.o : xqdbm.h xadbm.h xcuria.h xvilla.o xvltest.o : xqdbm.h xadbm.h xvilla.h # END OF FILE qdbm-1.8.78/plus/xvltest.cc0000644000175000017500000004061310505724131014551 0ustar mikiomikio/************************************************************************************************* * Test cases of Villa for C++ * Copyright (C) 2000-2005 Mikio Hirabayashi * This file is part of QDBM, Quick Database Manager. * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU * Lesser General Public License as published by the Free Software Foundation; either version * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * You should have received a copy of the GNU Lesser General Public License along with QDBM; if * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. *************************************************************************************************/ #include #include #include #include #include #include #include #include extern "C" { #include #include #include } using namespace std; using namespace qdbm; /* global constants */ const int RECBUFSIZ = 32; const int LRECMAX = 25; const int NIDXMAX = 64; const int LCNUM = 32; const int NCNUM = 32; /* struct for closure per thread */ struct Mission { Villa* villa; int rnum; int id; bool printer; }; /* global variables */ const char* progname; /* function prototypes */ int main(int argc, char** argv); void myterminate(); void myunexpected(); void usage(); int runwrite(int argc, char** argv); int runread(int argc, char** argv); int runmulti(int argc, char** argv); int runmisc(int argc, char** argv); void pxdperror(const char* name, DBM_error &e); int myrand(void); int dowrite(const char* name, int rnum); int doread(const char* name); int domulti(const char* name, int rnum, int tnum); void* mtwriter(void* arg); int domisc(const char* name); /* main routine */ int main(int argc, char** argv){ int rv; set_terminate(myterminate); set_unexpected(myunexpected); progname = argv[0]; if(argc < 2) usage(); rv = 0; if(!strcmp(argv[1], "write")){ rv = runwrite(argc, argv); } else if(!strcmp(argv[1], "read")){ rv = runread(argc, argv); } else if(!strcmp(argv[1], "multi")){ rv = runmulti(argc, argv); } else if(!strcmp(argv[1], "misc")){ rv = runmisc(argc, argv); } else { usage(); } return rv; } /* for debug */ void myterminate(){ cout << progname << ": terminate" << endl; exit(1); } /* for debug */ void myunexpected(){ cout << progname << ": unexpected" << endl; exit(1); } /* print the usage and exit */ void usage(){ cerr << progname << ": test cases for Villa for C++" << endl; cerr << endl; cerr << "usage:" << endl; cerr << " " << progname << " write name rnum" << endl; cerr << " " << progname << " read name" << endl; cerr << " " << progname << " multi name rnum tnum" << endl; cerr << " " << progname << " misc name" << endl; cerr << endl; exit(1); } /* parse arguments of write command */ int runwrite(int argc, char** argv){ char *name, *rstr; int i, rnum, rv; name = 0; rstr = 0; for(i = 2; i < argc; i++){ if(argv[i][0] == '-'){ usage(); } else if(!name){ name = argv[i]; } else if(!rstr){ rstr = argv[i]; } else { usage(); } } if(!name || !rstr) usage(); rnum = atoi(rstr); if(rnum < 1) usage(); rv = dowrite(name, rnum); return rv; } /* parse arguments of read command */ int runread(int argc, char** argv){ char* name; int i, rv; name = 0; for(i = 2; i < argc; i++){ if(argv[i][0] == '-'){ usage(); } else if(!name){ name = argv[i]; } else { usage(); } } if(!name) usage(); rv = doread(name); return rv; } /* parse arguments of multi command */ int runmulti(int argc, char** argv){ char *name, *rstr, *tstr; int i, rnum, tnum, rv; name = 0; rstr = 0; tstr = 0; for(i = 2; i < argc; i++){ if(argv[i][0] == '-'){ usage(); } else if(!name){ name = argv[i]; } else if(!rstr){ rstr = argv[i]; } else if(!tstr){ tstr = argv[i]; } else { usage(); } } if(!name || !rstr || !tstr) usage(); rnum = atoi(rstr); tnum = atoi(tstr); if(rnum < 1 || tnum < 1) usage(); rv = domulti(name, rnum, tnum); return rv; } /* parse arguments of misc command */ int runmisc(int argc, char** argv){ char* name; int i, rv; name = 0; for(i = 2; i < argc; i++){ if(argv[i][0] == '-'){ usage(); } else if(!name){ name = argv[i]; } else { usage(); } } if(!name) usage(); rv = domisc(name); return rv; } /* print an error message */ void pxdperror(const char* name, DBM_error &e){ cerr << progname << ": " << name << ": " << e << endl; } /* pseudo random number generator */ int myrand(void){ static int cnt = 0; if(cnt == 0) std::srand(std::time(NULL)); return (std::rand() * std::rand() + (std::rand() >> (sizeof(int) * 4)) + (cnt++)) & 0x7FFFFFFF; } /* do writing test */ int dowrite(const char* name, int rnum){ int i, len; char buf[RECBUFSIZ]; cout << "" << endl; cout << " name=" << name << " rnum=" << rnum << endl; cout << endl; Villa* villa = 0; bool err = false; try { // open the database villa = new Villa(name, Villa::OWRITER | Villa::OCREAT | Villa::OTRUNC); // roop for storing for(i = 1; i <= rnum; i++){ // set a buffer for a key and a value len = sprintf(buf, "%08d", i); // store a record into the database villa->put(buf, len, buf, len); // print progression if(rnum > 250 && i % (rnum / 250) == 0){ cout << '.'; cout.flush(); if(i == rnum || i % (rnum / 10) == 0){ cout << " (" << setw(8) << setfill('0') << i << ")" << endl; cout.flush(); } } } // close the database villa->close(); cout << "ok" << endl << endl; } catch(Villa_error& e){ err = true; // report an error pxdperror(name, e); } // destroy instance if(villa) delete villa; return err ? 1 : 0; } /* do reading test */ int doread(const char* name){ int i, rnum, len; char buf[RECBUFSIZ], *val; cout << "" << endl; cout << " name=" << name << endl; cout << endl; Villa* villa = 0; bool err = false; try { // open the database villa = new Villa(name); // get the number of records rnum = villa->rnum(); // roop for retrieving for(i = 1; i <= rnum; i++){ // set a buffer for a key len = sprintf(buf, "%08d", i); // retrieve a record from the database val = villa->get(buf, len); free(val); // print progression if(rnum > 250 && i % (rnum / 250) == 0){ cout << '.'; cout.flush(); if(i == rnum || i % (rnum / 10) == 0){ cout << " (" << setw(8) << setfill('0') << i << ")" << endl; cout.flush(); } } } // close the database villa->close(); cout << "ok" << endl << endl; } catch(Villa_error& e){ err = true; // report an error pxdperror(name, e); } // destroy instance if(villa) delete villa; return err ? 1 : 0; } /* do multi thread test */ int domulti(const char* name, int rnum, int tnum){ Villa* villa; pthread_t* tids; bool* tsts; Mission* mss; Villa_error* ep; int i, len, size, vnum; bool err; char buf[RECBUFSIZ], *val; cout << "" << endl; cout << " name=" << name << " rnum=" << rnum << " tnum=" << tnum << endl; cout << endl; // open the database villa = 0; try { cout << "Creating a database ... "; villa = new Villa(name, Villa::OWRITER | Villa::OCREAT | Villa::OTRUNC); villa->settuning(LRECMAX, NIDXMAX, LCNUM, NCNUM); cout << "ok" << endl; } catch(Villa_error& e){ if(villa) delete villa; pxdperror(name, e); return 1; } // prepare threads tids = new pthread_t[tnum]; tsts = new bool[tnum]; mss = new Mission[tnum]; err = false; // roop for each threads cout << "Writing" << endl; for(i = 0; i < tnum; i++){ mss[i].villa = villa; mss[i].rnum = rnum; mss[i].id = i; mss[i].printer = (i == tnum / 2); if(pthread_create(tids + i, 0, mtwriter, (void*)(mss + i)) == 0){ tsts[i] = true; } else { tsts[i] = false; err = true; cerr << progname << ": " << name << ": " << "pthread error" << endl; } } // join every threads for(i = 0; i < tnum; i++){ if(tsts[i]){ if(pthread_join(tids[i], (void**)&ep) != 0){ err = true; cerr << progname << ": " << name << ": " << "pthread error" << endl; } } if(ep){ err = true; pxdperror(name, *ep); delete ep; } } delete[] mss; delete[] tsts; delete[] tids; if(!err) cout << "ok" << endl; cout.flush(); // check every record cout << "Validation checking ... "; try { for(i = 1; i <= rnum; i++){ len = sprintf(buf, "%08d", i); val = villa->get(buf, len, &size); free(val); if(size != 1 || villa->vsiz(buf, len) != 1){ cerr << progname << ": " << name << ": " << "size error: " << size << endl; err = true; } vnum = villa->vnum(buf, len); if(vnum != tnum){ cerr << progname << ": " << name << ": " << "vnum error: " << vnum << endl; err = true; } } } catch(Villa_error& e){ pxdperror(name, e); err = true; } if(!err) cout << "ok" << endl; // close the database cout << "Closing the database ... "; try { villa->close(); } catch(Villa_error& e){ pxdperror(name, e); delete villa; return 1; } cout << "ok" << endl; if(!err) cout << "all ok" << endl << endl; delete villa; return err ? 1 : 0; } /* writer with each thread */ void* mtwriter(void* arg){ Mission* mp = (Mission*)arg; Villa* villa = mp->villa; int rnum = mp->rnum; int id = mp->id; bool printer = mp->printer; char buf[RECBUFSIZ]; void* mc; int i, len; // roop for storing for(i = 1; i <= rnum; i++){ len = sprintf(buf, "%08d", i); // store a record bool tran = false; try { if(myrand() % (mp->rnum / 7 + 1) == 0){ villa->tranbegin(); tran = true; } villa->put(buf, len, id % 2 ? "*" : "=", 1, Villa::DDUP); } catch(Villa_error& e){ if(tran) villa->tranabort(); return new Villa_error(e); } if(tran) villa->trancommit(); // print progression if(printer && rnum > 250 && i % (rnum / 250) == 0){ cout << '.'; cout.flush(); if(i == rnum || i % (rnum / 10) == 0){ cout << " (" << setw(8) << setfill('0') << i << ")" << endl; cout.flush(); } } // malloc reentrant check if((mc = (char*)malloc(1)) != 0){ free(mc); } else { return new Villa_error(Villa::EALLOC); } } return 0; } /* do combination test */ int domisc(const char* name){ bool err; int i, len; char buf[RECBUFSIZ], *tmp; cout << "" << endl; cout << " name=" << name << endl; cout << endl; err = false; ADBM* adbm = 0; try { // open the database cout << "Creating a database ... "; adbm = new Villa(name, Villa::OWRITER | Villa::OCREAT | Villa::OTRUNC); cout << "ok" << endl; // write with datadase abstraction cout << "Writing with database abstraction ... "; for(i = 1; i <= 100; i++){ len = sprintf(buf, "%08d", i); Datum key(buf, len); Datum val(buf, len); adbm->storerec(key, val, true); } cout << "ok" << endl; // read with datadase abstraction cout << "Reading with database abstraction ... "; for(i = 1; i <= 100; i++){ len = sprintf(buf, "%08d", i); Datum key(buf, len); const Datum& val = adbm->fetchrec(key); len = val.size(); if(len != 8) throw DBM_error("size error"); } cout << "ok" << endl; // traversal access with database abstraction cout << "Traversal access with database abstraction ... "; i = 0; try { for(adbm->firstkey(); true; adbm->nextkey()){ i++; } } catch(DBM_error& e){ if(adbm->error()) throw; } if(i != 100) throw DBM_error("iteration error"); cout << "ok" << endl; // close the database cout << "Closing the database ... "; adbm->close(); cout << "ok" << endl; } catch(DBM_error& e){ err = true; pxdperror(name, e); } if(adbm) delete adbm; if(err) return 1; Villa* villa = 0; try { // open the database cout << "Opening the database ... "; villa = new Villa(name); cout << "ok" << endl; // traversal access cout << "Traversal access ... "; try { villa->curfirst(); for(i = 0; true; i++){ villa->curnext(); } if(i != 100) throw Villa_error(); } catch(Villa_error& e){ if(e != Villa::ENOITEM) throw; } cout << "ok" << endl; // checking information cout << "Checking information" << endl; cout << " - fsiz ... " << villa->fsiz() << endl; cout << " - lnum ... " << villa->lnum() << endl; cout << " - nnum ... " << villa->nnum() << endl; cout << " - rnum ... " << villa->rnum() << endl; cout << " - writable ... " << villa->writable() << endl; cout << " - fatalerror ... " << villa->fatalerror() << endl; cout << " - inode ... " << villa->inode() << endl; cout << " - mtime ... " << villa->mtime() << endl; cout << "ok" << endl; // close the database cout << "Closing the database ... "; villa->close(); cout << "ok" << endl; } catch(Villa_error& e){ err = true; pxdperror(name, e); } if(villa) delete villa; if(err) return 1; villa = 0; try { // open the database cout << "Opening the database ... "; villa = new Villa(name, Villa::OWRITER); villa->silent = true; cout << "ok" << endl; // sync the database cout << "Syncing the database ... "; villa->sync(); cout << "ok" << endl; // optimize the database cout << "Optimizing the database ... "; villa->optimize(); cout << "ok" << endl; // write in silent mode cout << "Writing in silent mode ... "; for(i = 1; i <= 100; i++){ len = sprintf(buf, "%d", rand() % 100); villa->put(buf, len, buf, len, Villa::DKEEP); } cout << "ok" << endl; // read in silent mode cout << "Reading in silent mode ... "; for(i = 1; i <= 100; i++){ len = sprintf(buf, "%d", rand() % 100); if((tmp = villa->get(buf, len)) != 0) free(tmp); } cout << "ok" << endl; // traversal access cout << "Traversal access in silent mode ... "; villa->curfirst(); while((tmp = villa->curkey()) != 0){ free(tmp); villa->curnext(); } cout << "ok" << endl; // close the database cout << "Closing the database ... "; villa->close(); cout << "ok" << endl; } catch(Villa_error& e){ err = true; pxdperror(name, e); } if(villa) delete villa; if(err) return 1; villa = 0; try { // open the database cout << "Opening the database with leaves compressed ... "; Villa zvilla(name, Villa::OWRITER | Villa::OCREAT | Villa::OTRUNC | Villa::OZCOMP); cout << "ok" << endl; // write records cout << "Writing records ... "; for(i = 1; i <= 100; i++){ len = sprintf(buf, "%08d", i); zvilla.put(buf, len, buf,len, Villa::DCAT); zvilla.put(buf, len, buf,len, Villa::DDUP); zvilla.put(buf, len, buf,len, Villa::DCAT); } cout << "ok" << endl; // read records cout << "Checking records ... "; for(i = 1; i <= 100; i++){ len = sprintf(buf, "%08d", i); if(zvilla.vnum(buf, len) != 2) throw Villa_error(); } cout << "ok" << endl; // cursor operations cout << "Cursor operations ... "; zvilla.curjump("00000010", -1, Villa::JFORWARD); zvilla.curput("CURRENT", -1, Villa::CPCURRENT); zvilla.curput("BEFORE", -1, Villa::CPBEFORE); zvilla.curput("AFTER", -1, Villa::CPAFTER); zvilla.curnext(); zvilla.curout(); zvilla.curput("OMIT", -1); cout << "ok" << endl; // close the database cout << "Closing the database ... "; zvilla.close(); cout << "ok" << endl; } catch(Villa_error& e){ err = true; pxdperror(name, e); } if(err) return 1; cout << "all ok" << endl << endl; return 0; } /* END OF FILE */ qdbm-1.8.78/plus/overview0000644000175000017500000000342011426314407014321 0ustar mikiomikio/** * @mainpage *

QDBM is a library of routines for managing a database. The database is a simple data file containing records, each is a pair of a key and a value. Every key and value is serial bytes with variable length. Both binary data and character string can be used as a key and a value. There is neither concept of data tables nor data types. Records are organazed in hash table or B+ tree.

*

As for database of hash table, each key must be unique within a database, so it is impossible to store two or more records with a key overlaps. The following access methods are provided to the database: storing a record with a key and a value, deleting a record by a key, retrieving a record by a key. Moreover, traversal access to every key are provided, although the order is arbitrary. These access methods are similar to ones of DBM (or its followers, NDBM and GDBM) library defined in the UNIX standard. QDBM is an alternative for DBM because of its higher performance.

*

As for database of B+ tree, records whose keys are duplicated can be stored. Access methods of storing, deleting and retrieving are provided as with the database of hash table. Records are stored in order by a comparing function assigned by a user. It is possible to access each record with the cursor in ascending or descending order. According to this mechanism, forward matching search for strings and range search for integers are realized. Moreover, transaction is available in database of B+ tree.

*

QDBM provides API for C++. This encapsulates the basic API and the extended API of QDBM, and make them thread-safe. Each class is packaged in the namespace `qdbm'.

*

Refer to `http://fallabs.com/qdbm/' for more information.

*/ qdbm-1.8.78/plus/xadbm.cc0000644000175000017500000001421010252103647014127 0ustar mikiomikio/************************************************************************************************* * Abstraction for database managers compatible with DBM * Copyright (C) 2000-2005 Mikio Hirabayashi * This file is part of QDBM, Quick Database Manager. * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU * Lesser General Public License as published by the Free Software Foundation; either version * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * You should have received a copy of the GNU Lesser General Public License along with QDBM; if * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. *************************************************************************************************/ #include "xadbm.h" #include #include #include using namespace qdbm; /************************************************************************************************* * private objects *************************************************************************************************/ namespace { char *xmalloc(size_t size) throw(std::bad_alloc); char *xrealloc(void *ptr, size_t size) throw(std::bad_alloc); char *xmalloc(size_t size) throw(std::bad_alloc){ char *p; if(!(p = (char*)std::malloc(size))) throw std::bad_alloc(); return p; } char *xrealloc(void *ptr, size_t size) throw(std::bad_alloc){ char *p; if(!(p = (char*)std::realloc(ptr, size))) throw std::bad_alloc(); return p; } } /************************************************************************************************* * DBM_error *************************************************************************************************/ DBM_error::DBM_error() throw(){ errmsg = 0; } DBM_error::DBM_error(const char* message) throw(){ int len = std::strlen(message); this->errmsg = xmalloc(len + 1); std::memcpy(this->errmsg, message, len); this->errmsg[len] = '\0'; } DBM_error::~DBM_error() throw(){ if(errmsg) std::free(errmsg); } DBM_error::operator const char*() const throw(){ if(!errmsg) return "database error"; return errmsg; } const char* DBM_error::message() const throw(){ if(!errmsg) return "database error"; return errmsg; } /************************************************************************************************* * Datum *************************************************************************************************/ Datum::Datum(const char* dptr, int dsize){ if(dsize < 0) dsize = std::strlen(dptr); this->dptr = xmalloc(dsize + 1); std::memcpy(this->dptr, dptr, dsize); this->dptr[dsize] = '\0'; this->dsize = dsize; } Datum::Datum(int num){ this->dptr = xmalloc(sizeof(num)); std::memcpy(this->dptr, &num, sizeof(num)); this->dsize = sizeof(num); } Datum::Datum(const Datum& datum){ this->dptr = xmalloc(datum.dsize + 1); std::memcpy(this->dptr, datum.dptr, datum.dsize); this->dptr[datum.dsize] = '\0'; this->dsize = datum.dsize; } Datum::~Datum() throw(){ std::free(dptr); } Datum& Datum::operator =(const Datum& datum){ if(this == &datum) return *this; std::free(this->dptr); this->dptr = xmalloc(datum.dsize + 1); std::memcpy(this->dptr, datum.dptr, datum.dsize); this->dptr[datum.dsize] = '\0'; this->dsize = datum.dsize; return *this; } Datum& Datum::operator =(const char* str){ std::free(this->dptr); dsize = std::strlen(str); dptr = xmalloc(dsize + 1); std::memcpy(dptr, str, dsize); dptr[dsize] = '\0'; return *this; } Datum& Datum::operator <<(const Datum& datum){ dptr = xrealloc(dptr, dsize + datum.dsize + 1); std::memcpy(dptr + dsize, datum.dptr, datum.dsize); dsize += datum.dsize; dptr[dsize] = '\0'; return *this; } Datum& Datum::operator <<(const char* str){ int len = strlen(str); dptr = xrealloc(dptr, dsize + len + 1); std::memcpy(dptr + dsize, str, len); dsize += len; dptr[dsize] = '\0'; return *this; } bool Datum::operator ==(const Datum& datum) const { if(dsize != datum.dsize) return false; return std::memcmp(dptr, datum.dptr, dsize) == 0 ? true : false; } bool Datum::operator !=(const Datum& datum) const { if(dsize != datum.dsize) return true; return std::memcmp(dptr, datum.dptr, dsize) == 0 ? false : true; } bool Datum::operator ==(const char* str) const { int len = strlen(str); if(dsize != len) return false; return std::memcmp(dptr, str, len) == 0 ? true : false; } bool Datum::operator !=(const char* str) const { int len = strlen(str); if(dsize != len) return true; return std::memcmp(dptr, str, len) == 0 ? false : true; } char& Datum::operator [](int idx) const { return dptr[idx]; } Datum::operator const char*() const { return dptr; } const char* Datum::ptr() const { return dptr; } int Datum::size() const { return dsize; } Datum::Datum(char* dptr, int dsize, bool dummy){ this->dptr = xrealloc(dptr, dsize + 1); this->dptr[dsize] = '\0'; this->dsize = dsize; } Datum qdbm::operator +(const Datum& former, const Datum& latter){ int len = former.dsize + latter.dsize; char *buf = xmalloc(former.dsize + latter.dsize + 1); std::memcpy(buf, former.dptr, former.dsize); std::memcpy(buf + former.dsize, latter.dptr, latter.dsize); buf[len] = '\0'; return Datum(buf, len, true); } Datum qdbm::operator +(const Datum& datum, const char* str){ int len = strlen(str); char* buf = xmalloc(datum.dsize + len + 1); std::memcpy(buf, datum.dptr, datum.dsize); std::memcpy(buf + datum.dsize, str, len); len += datum.dsize; buf[len] = '\0'; return Datum(buf, len, true); } Datum qdbm::operator +(const char* str, const Datum& datum){ int len = strlen(str); char* buf = xmalloc(len + datum.dsize + 1); std::memcpy(buf, str, len); std::memcpy(buf + len, datum.dptr, datum.dsize); len += datum.dsize; buf[len] = '\0'; return Datum(buf, len, true); } /* END OF FILE */ qdbm-1.8.78/plus/configure.in0000644000175000017500000001032710573423336015051 0ustar mikiomikio# Source of configuration for C++ interface of QDBM #================================================================ # Generic Settings #================================================================ # Targets AC_INIT(qdbm-plus, 1.0.0) # Export variables LIBVER=3 LIBREV=0 TARGETS="all" MYDEFS="" MYOPTS="" LD="ld" AR="ar" # Building paths pathtmp="$PATH" PATH="$HOME/bin:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin" PATH="$PATH:/usr/ccs/bin:/usr/ucb:/usr/xpg4/bin:/usr/xpg6/bin:$pathtmp" LIBRARY_PATH="$HOME/lib:/usr/local/lib:$LIBRARY_PATH" LD_LIBRARY_PATH="$HOME/lib:/usr/local/lib:$LD_LIBRARY_PATH" CPATH="$HOME/include:/usr/local/include:$CPATH" export PATH LIBRARY_PATH LD_LIBRARY_PATH CPATH #================================================================ # Options #================================================================ # Debug mode AC_ARG_ENABLE(debug, [ --enable-debug build for debugging]) if test "$enable_debug" = "yes" then TARGETS="debug" fi # Developping mode AC_ARG_ENABLE(devel, [ --enable-devel build for development]) if test "$enable_devel" = "yes" then TARGETS="devel" fi #================================================================ # Checking Commands to Build with #================================================================ # C compiler AC_PROG_CC # C++ compiler AC_PROG_CXX if test "$GXX" != "yes" then printf '#================================================================\n' 1>&2 printf '# WARNING: g++ (GCC) is required to build this package.\n' 1>&2 printf '#================================================================\n' 1>&2 fi if uname | egrep -i 'SunOS' > /dev/null 2>&1 then MYOPTS="-O1" fi if uname | egrep -i 'BSD' > /dev/null 2>&1 then MYOPTS="-O1" fi if gcc --version | egrep -i '^2\.(8|9)' > /dev/null 2>&1 then MYOPTS="-O1" fi # Linker printf 'checking for ld... ' if which ld | grep '/ld$' > /dev/null 2>&1 then LD=`which ld` printf '%s\n' "$LD" else printf 'no\n' printf '#================================================================\n' 1>&2 printf '# WARNING: ld is not found in PATH.\n' 1>&2 printf '#================================================================\n' 1>&2 fi # Archiver printf 'checking for ar... ' if which ar | grep '/ar$' > /dev/null 2>&1 then AR=`which ar` printf '%s\n' "$AR" else printf 'no\n' printf '#================================================================\n' 1>&2 printf '# WARNING: ar is not found in PATH.\n' 1>&2 printf '#================================================================\n' 1>&2 fi #================================================================ # Checking Libraries #================================================================ # Underlying libraries AC_CHECK_LIB(c, main) AC_CHECK_LIB(rt, main) AC_CHECK_LIB(pthread, main) AC_CHECK_LIB(z, main) AC_CHECK_LIB(lzo2, main) AC_CHECK_LIB(bz2, main) AC_CHECK_LIB(iconv, main) AC_CHECK_LIB(stdc++, main) # Fundamental QDBM libraries AC_CHECK_LIB(qdbm, main, true, printf 'checking whether /usr/local/lib/libqdbm.* is... ' if ls /usr/local/lib/libqdbm.* > /dev/null 2>&1 then printf 'yes\n' else printf 'no\n' printf '#================================================================\n' 1>&2 printf '# WARNING: Install QDBM libraries before installation.\n' 1>&2 printf '#================================================================\n' 1>&2 fi ) # For old BSDs if uname -a | grep BSD > /dev/null && test -f /usr/lib/libc_r.a && test ! -f /usr/lib/libpthread.a then LIBS=`printf '%s' "$LIBS" | sed 's/-lc/-lc_r/g'` fi # Duplication of QDBM for C++ AC_CHECK_LIB(xqdbm, main, printf '#================================================================\n' 1>&2 printf '# WARNING: The existing library was detected.\n' 1>&2 printf '#================================================================\n' 1>&2 ) #================================================================ # Generic Settings #================================================================ # Export variables AC_SUBST(LIBVER) AC_SUBST(LIBREV) AC_SUBST(TARGETS) AC_SUBST(MYDEFS) AC_SUBST(MYOPTS) AC_SUBST(LD) AC_SUBST(AR) AC_SUBST(CPPFLAGS) AC_SUBST(LDFLAGS) # Targets AC_OUTPUT(Makefile) # END OF FILE qdbm-1.8.78/plus/xqdbm.h0000644000175000017500000000334210470507421014015 0ustar mikiomikio/************************************************************************************************* * Common setting for QDBM * Copyright (C) 2000-2006 Mikio Hirabayashi * This file is part of QDBM, Quick Database Manager. * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU * Lesser General Public License as published by the Free Software Foundation; either version * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * You should have received a copy of the GNU Lesser General Public License along with QDBM; if * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. *************************************************************************************************/ #ifndef _XQDBM_H /* duplication check */ #define _XQDBM_H extern "C" { #include } /** * Namespace of QDBM. */ namespace qdbm { class DBM_error; class Datum; Datum operator +(const Datum& former, const Datum& latter); Datum operator +(const Datum& datum, const char* str); Datum operator +(const char* str, const Datum& datum); class ADBM; class Depot_error; class Depot; class Curia_error; class Curia; class Villa_error; class Villa; extern pthread_mutex_t ourmutex; } /** * Common Mutex of QDBM. */ extern pthread_mutex_t qdbm::ourmutex; #endif /* duplication check */ /* END OF FILE */ qdbm-1.8.78/plus/xdepot.cc0000644000175000017500000003000010505666577014353 0ustar mikiomikio/************************************************************************************************* * Implementation of Depot for C++ * Copyright (C) 2000-2005 Mikio Hirabayashi * This file is part of QDBM, Quick Database Manager. * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU * Lesser General Public License as published by the Free Software Foundation; either version * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * You should have received a copy of the GNU Lesser General Public License along with QDBM; if * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. *************************************************************************************************/ #include "xdepot.h" #include #include #include extern "C" { #include #include } using namespace qdbm; /************************************************************************************************* * Depot_error *************************************************************************************************/ Depot_error::Depot_error() throw() : DBM_error(){ ecode = DP_EMISC; return; } Depot_error::Depot_error(int ecode) throw() : DBM_error(){ this->ecode = ecode; return; } Depot_error::Depot_error(const Depot_error& de) throw() : DBM_error(de){ ecode = de.ecode; return; } Depot_error::~Depot_error() throw(){ return; } Depot_error& Depot_error::operator =(const Depot_error& de) throw(){ this->ecode = de.ecode; return *this; } Depot_error& Depot_error::operator =(int ecode) throw(){ this->ecode = ecode; return *this; } bool Depot_error::operator ==(const Depot_error& de) const throw(){ return ecode == de.ecode; } bool Depot_error::operator !=(const Depot_error& de) const throw(){ return ecode != de.ecode; } bool Depot_error::operator ==(int ecode) const throw(){ return this->ecode == ecode; } bool Depot_error::operator !=(int ecode) const throw(){ return this->ecode != ecode; } Depot_error::operator const char*() const throw(){ return dperrmsg(ecode); } int Depot_error::code() const throw(){ return ecode; } const char* Depot_error::message() const throw(){ return dperrmsg(ecode); } /************************************************************************************************* * Depot *************************************************************************************************/ const int Depot::ENOERR = DP_ENOERR; const int Depot::EFATAL = DP_EFATAL; const int Depot::EMODE = DP_EMODE; const int Depot::EBROKEN = DP_EBROKEN; const int Depot::EKEEP = DP_EKEEP; const int Depot::ENOITEM = DP_ENOITEM; const int Depot::EALLOC = DP_EALLOC; const int Depot::EMAP = DP_EMAP; const int Depot::EOPEN = DP_EOPEN; const int Depot::ECLOSE = DP_ECLOSE; const int Depot::ETRUNC = DP_ETRUNC; const int Depot::ESYNC = DP_ESYNC; const int Depot::ESTAT = DP_ESTAT; const int Depot::ESEEK = DP_ESEEK; const int Depot::EREAD = DP_EREAD; const int Depot::EWRITE = DP_EWRITE; const int Depot::ELOCK = DP_ELOCK; const int Depot::EUNLINK = DP_EUNLINK; const int Depot::EMKDIR = DP_EMKDIR; const int Depot::ERMDIR = DP_ERMDIR; const int Depot::EMISC = DP_EMISC; const int Depot::OREADER = DP_OREADER; const int Depot::OWRITER = DP_OWRITER; const int Depot::OCREAT = DP_OCREAT; const int Depot::OTRUNC = DP_OTRUNC; const int Depot::ONOLCK = DP_ONOLCK; const int Depot::OLCKNB = DP_OLCKNB; const int Depot::OSPARSE = DP_OSPARSE; const int Depot::DOVER = DP_DOVER; const int Depot::DKEEP = DP_DKEEP; const int Depot::DCAT = DP_DCAT; const char* Depot::version() throw(){ return dpversion; } void Depot::remove(const char* name) throw(Depot_error){ if(pthread_mutex_lock(&ourmutex) != 0) throw Depot_error(); if(!dpremove(name)){ int ecode = dpecode; pthread_mutex_unlock(&ourmutex); throw Depot_error(ecode); } pthread_mutex_unlock(&ourmutex); } char* Depot::snaffle(const char* name, const char* kbuf, int ksiz, int* sp) throw(Depot_error){ char* vbuf; if(pthread_mutex_lock(&ourmutex) != 0) throw Depot_error(); if(!(vbuf = dpsnaffle(name, kbuf, ksiz, sp))){ int ecode = dpecode; pthread_mutex_unlock(&ourmutex); throw Depot_error(ecode); } pthread_mutex_unlock(&ourmutex); return vbuf; } Depot::Depot(const char* name, int omode, int bnum) throw(Depot_error) : ADBM(){ pthread_mutex_init(&mymutex, NULL); silent = false; if(!lock()) throw Depot_error(); if(!(depot = dpopen(name, omode, bnum))){ int ecode = dpecode; unlock(); throw Depot_error(ecode); } unlock(); } Depot::~Depot() throw(){ if(!depot){ pthread_mutex_destroy(&mymutex); return; } if(lock()){ dpclose(depot); unlock(); } depot = 0; pthread_mutex_destroy(&mymutex); } void Depot::close() throw(Depot_error){ if(!depot) throw Depot_error(); if(!lock()) throw Depot_error(); if(!dpclose(depot)){ int ecode = dpecode; depot = 0; unlock(); throw Depot_error(ecode); } depot = 0; unlock(); } bool Depot::put(const char* kbuf, int ksiz, const char* vbuf, int vsiz, int dmode) throw(Depot_error){ if(!depot) throw Depot_error(); if(!lock()) throw Depot_error(); if(!dpput(depot, kbuf, ksiz, vbuf, vsiz, dmode)){ int ecode = dpecode; unlock(); if(silent && ecode == EKEEP) return false; throw Depot_error(ecode); } unlock(); return true; } bool Depot::out(const char* kbuf, int ksiz) throw(Depot_error){ if(!depot) throw Depot_error(); if(!lock()) throw Depot_error(); if(!dpout(depot, kbuf, ksiz)){ int ecode = dpecode; unlock(); if(silent && ecode == ENOITEM) return false; throw Depot_error(ecode); } unlock(); return true; } char* Depot::get(const char* kbuf, int ksiz, int start, int max, int* sp) throw(Depot_error){ char* vbuf; if(!depot) throw Depot_error(); if(!lock()) throw Depot_error(); if(!(vbuf = dpget(depot, kbuf, ksiz, start, max, sp))){ int ecode = dpecode; unlock(); if(silent && ecode == ENOITEM) return 0; throw Depot_error(ecode); } unlock(); return vbuf; } int Depot::getwb(const char *kbuf, int ksiz, int start, int max, char *vbuf) throw(Depot_error){ int vsiz; if(!depot) throw Depot_error(); if(!lock()) throw Depot_error(); if((vsiz = dpgetwb(depot, kbuf, ksiz, start, max, vbuf)) == -1){ int ecode = dpecode; unlock(); if(silent && ecode == ENOITEM) return -1; throw Depot_error(ecode); } unlock(); return vsiz; } int Depot::vsiz(const char* kbuf, int ksiz) throw(Depot_error){ int vsiz; if(!depot) throw Depot_error(); if(!lock()) throw Depot_error(); if((vsiz = dpvsiz(depot, kbuf, ksiz)) == -1){ int ecode = dpecode; unlock(); if(silent && ecode == ENOITEM) return -1; throw Depot_error(ecode); } unlock(); return vsiz; } void Depot::iterinit() throw(Depot_error){ if(!depot) throw Depot_error(); if(!lock()) throw Depot_error(); if(!dpiterinit(depot)){ int ecode = dpecode; unlock(); throw Depot_error(ecode); } unlock(); } char* Depot::iternext(int* sp) throw(Depot_error){ char* vbuf; if(!depot) throw Depot_error(); if(!lock()) throw Depot_error(); if(!(vbuf = dpiternext(depot, sp))){ int ecode = dpecode; unlock(); if(silent && ecode == ENOITEM) return 0; throw Depot_error(ecode); } unlock(); return vbuf; } void Depot::setalign(int align) throw(Depot_error){ if(!depot) throw Depot_error(); if(!lock()) throw Depot_error(); if(!dpsetalign(depot, align)){ int ecode = dpecode; unlock(); throw Depot_error(ecode); } unlock(); } void Depot::setfbpsiz(int size) throw(Depot_error){ if(!depot) throw Depot_error(); if(!lock()) throw Depot_error(); if(!dpsetfbpsiz(depot, size)){ int ecode = dpecode; unlock(); throw Depot_error(ecode); } unlock(); } void Depot::sync() throw(Depot_error){ if(!depot) throw Depot_error(); if(!lock()) throw Depot_error(); if(!dpsync(depot)){ int ecode = dpecode; unlock(); throw Depot_error(ecode); } unlock(); } void Depot::optimize(int bnum) throw(Depot_error){ if(!depot) throw Depot_error(); if(!lock()) throw Depot_error(); if(!dpoptimize(depot, bnum)){ int ecode = dpecode; unlock(); throw Depot_error(ecode); } unlock(); } char* Depot::name() throw(Depot_error){ char* buf; if(!depot) throw Depot_error(); if(!lock()) throw Depot_error(); if(!(buf = dpname(depot))){ int ecode = dpecode; unlock(); throw Depot_error(ecode); } unlock(); return buf; } int Depot::fsiz() throw(Depot_error){ int rv; if(!depot) throw Depot_error(); if(!lock()) throw Depot_error(); if((rv = dpfsiz(depot)) == -1){ int ecode = dpecode; unlock(); throw Depot_error(ecode); } unlock(); return rv; } int Depot::bnum() throw(Depot_error){ int rv; if(!depot) throw Depot_error(); if(!lock()) throw Depot_error(); if((rv = dpbnum(depot)) == -1){ int ecode = dpecode; unlock(); throw Depot_error(ecode); } unlock(); return rv; } int Depot::busenum() throw(Depot_error){ int rv; if(!depot) throw Depot_error(); if(!lock()) throw Depot_error(); if((rv = dpbusenum(depot)) == -1){ int ecode = dpecode; unlock(); throw Depot_error(ecode); } unlock(); return rv; } int Depot::rnum() throw(Depot_error){ int rv; if(!depot) throw Depot_error(); if(!lock()) throw Depot_error(); if((rv = dprnum(depot)) == -1){ int ecode = dpecode; unlock(); throw Depot_error(ecode); } unlock(); return rv; } bool Depot::writable() throw(Depot_error){ int rv; if(!depot) throw Depot_error(); if(!lock()) throw Depot_error(); rv = dpwritable(depot); unlock(); return rv ? true : false; } bool Depot::fatalerror() throw(Depot_error){ int rv; if(!depot) throw Depot_error(); if(!lock()) throw Depot_error(); rv = dpfatalerror(depot); unlock(); return rv ? true : false; } int Depot::inode() throw(Depot_error){ int rv; if(!depot) throw Depot_error(); if(!lock()) throw Depot_error(); rv = dpinode(depot); unlock(); return rv; } time_t Depot::mtime() throw(Depot_error){ time_t rv; if(!depot) throw Depot_error(); if(!lock()) throw Depot_error(); rv = dpmtime(depot); unlock(); return rv; } int Depot::fdesc() throw(Depot_error){ int rv; if(!depot) throw Depot_error(); if(!lock()) throw Depot_error(); rv = dpfdesc(depot); unlock(); return rv; } void Depot::storerec(const Datum& key, const Datum& val, bool replace) throw(Depot_error){ if(!put(key.ptr(), key.size(), val.ptr(), val.size(), replace ? DP_DOVER : DP_DKEEP)) throw Depot_error(EKEEP); } void Depot::deleterec(const Datum& key) throw(Depot_error){ if(!out(key.ptr(), key.size())) throw Depot_error(ENOITEM); } Datum Depot::fetchrec(const Datum& key) throw(Depot_error){ char* vbuf; int vsiz; vbuf = get(key.ptr(), key.size(), 0, -1, &vsiz); if(!vbuf) throw Depot_error(ENOITEM); return Datum(vbuf, vsiz, true); } Datum Depot::firstkey() throw(Depot_error){ iterinit(); return nextkey(); } Datum Depot::nextkey() throw(Depot_error){ char* kbuf; int ksiz; kbuf = iternext(&ksiz); if(!kbuf) throw Depot_error(ENOITEM); return Datum(kbuf, ksiz, true); } bool Depot::error() throw(Depot_error){ return fatalerror(); } Depot::Depot(const Depot& depot) throw(Depot_error){ throw Depot_error(); } Depot& Depot::operator =(const Depot& depot) throw(Depot_error){ throw Depot_error(); } bool Depot::lock(){ if(dpisreentrant){ if(pthread_mutex_lock(&mymutex) != 0) return false; return true; } if(pthread_mutex_lock(&ourmutex) != 0) return false; return true; } void Depot::unlock(){ if(dpisreentrant){ pthread_mutex_unlock(&mymutex); } else { pthread_mutex_unlock(&ourmutex); } } /* END OF FILE */ qdbm-1.8.78/plus/xadbm.h0000644000175000017500000002240610355663556014015 0ustar mikiomikio/************************************************************************************************* * Abstraction for database managers compatible with DBM * Copyright (C) 2000-2006 Mikio Hirabayashi * This file is part of QDBM, Quick Database Manager. * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU * Lesser General Public License as published by the Free Software Foundation; either version * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * You should have received a copy of the GNU Lesser General Public License along with QDBM; if * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. *************************************************************************************************/ #ifndef _XADBM_H /* duplication check */ #define _XADBM_H #include /** * Error container for ADBM. */ class qdbm::DBM_error { //---------------------------------------------------------------- // public member functions //---------------------------------------------------------------- public: /** * Create an instance. */ DBM_error() throw(); /** * Create an instance. * @param message the string of a error message. */ DBM_error(const char* message) throw(); /** * Release resources of the instance. */ virtual ~DBM_error() throw(); /** * Cast operator into pointer to char. * @return the pointer to the string. */ virtual operator const char*() const throw(); /** * Get the message. * @return the pointer to the string. */ virtual const char* message() const throw(); //---------------------------------------------------------------- // private member variables //---------------------------------------------------------------- private: /** The pointer to the region of the error message. */ char* errmsg; }; //---------------------------------------------------------------- // Outer operators for Datum //---------------------------------------------------------------- /** * Temporary concatenation operator for Datum. * @param former the former datum. * @param latter the latter datum. * @return reference to a temporary instance. */ qdbm::Datum qdbm::operator +(const qdbm::Datum& former, const qdbm::Datum& latter); /** * Temporary concatenation operator for Datum. * @param datum the former datum. * @param str the latter string. * @return reference to a temporary instance. */ qdbm::Datum qdbm::operator +(const qdbm::Datum& datum, const char* str); /** * Temporary concatenation operator for Datum. * @param str the former string. * @param datum the latter datum. * @return reference to a temporary instance. */ qdbm::Datum qdbm::operator +(const char* str, const qdbm::Datum& datum); /** * Datum of records for ADBM. */ class qdbm::Datum { //---------------------------------------------------------------- // public member functions //---------------------------------------------------------------- public: /** * Create an instance. * @param dptr the pointer to the region of data. * @param dsize the size of the region. If it is negative, the size is assigned * with `std::strlen(dptr)'. */ Datum(const char* dptr = "", int dsize = -1); /** * Create an instance. * @param num an integer number. */ Datum(int num); /** * Copy constructor. * @param datum a source instance. */ Datum(const Datum& datum); /** * Release resources of the instance. */ virtual ~Datum() throw(); /** * Assignment operator. * @param datum a source instance. * @return reference to itself. */ Datum& operator =(const Datum& datum); /** * Assignment operator. * @param str a source string. * @return reference to itself. */ Datum& operator =(const char* str); /** * Concatenation operator. * @param datum a latter instance. * @return reference to itself. */ virtual Datum& operator <<(const Datum& datum); /** * Concatenation operator. * @param str a latter string. * @return reference to itself. */ virtual Datum& operator <<(const char* str); /** * Equality operator. * @param datum a comparing instance. * @return true if both equal, else, false. */ virtual bool operator ==(const Datum& datum) const; /** * Inequality operator. * @param datum a comparing instance. * @return true if both do not equal, else, false. */ virtual bool operator !=(const Datum& datum) const; /** * Equality operator. * @param str a comparing string. * @return true if both equal, else, false. */ virtual bool operator ==(const char* str) const; /** * Inequality operator. * @param str a comparing string. * @return true if both do not equal, else, false. */ virtual bool operator !=(const char* str) const; /** * Subscripting operator. * @param idx the index of a character. * @return reference of the character. */ virtual char& operator [](int idx) const; /** * Cast operator into pointer to char. * @return the pointer of the region of the datum. * @note Because an additional zero code is appended at the end of the region of the return * value, the return value can be treated as a character string. */ virtual operator const char*() const; /** * Get the pointer of the region of the datum. * @return the pointer of the region of the datum. * @note Because an additional zero code is appended at the end of the region of the return * value, the return value can be treated as a character string. */ virtual const char* ptr() const; /** * Get the size of the region of the datum. * @return the size of the region of the datum. */ virtual int size() const; //---------------------------------------------------------------- // private member variables //---------------------------------------------------------------- private: /** The pointer to the region. */ char* dptr; /** The size of the region. */ int dsize; //---------------------------------------------------------------- // private member functions //---------------------------------------------------------------- private: /** * Create an instance. * @param dptr the region allocated with `std::malloc' or `std::realloc'. * @param dsize the size of the region. * @param dummy ignored. It is for difference of signature. * @note the specified region is released with `std::free' at the destruction of the instance. */ Datum(char* dptr, int dsize, bool dummy); //---------------------------------------------------------------- // friend classes and functions //---------------------------------------------------------------- friend class qdbm::Depot; friend class qdbm::Curia; friend class qdbm::Villa; friend Datum qdbm::operator +(const Datum& former, const Datum& latter); friend Datum qdbm::operator +(const Datum& datum, const char* str); friend Datum qdbm::operator +(const char* str, const Datum& datum); }; /** * Aabstraction for database managers compatible with DBM. */ class qdbm::ADBM { //---------------------------------------------------------------- // public member functions //---------------------------------------------------------------- public: /** * Release resources of the instance. */ virtual ~ADBM(){} /** * Close the database connection. * @throw DBM_error if an error occurs. */ virtual void close() throw(DBM_error) = 0; /** * Store a record. * @param key reference to a key object. * @param val reference to a value object. * @param replace whether the existing value is to be overwritten or not. * @throw DBM_error if an error occurs or replace is cancelled. */ virtual void storerec(const Datum& key, const Datum& val, bool replace = true) throw(DBM_error) = 0; /** * Delete a record. * @param key reference to a key object. * @throw DBM_error if an error occurs or no record corresponds. */ virtual void deleterec(const Datum& key) throw(DBM_error) = 0; /** * Fetch a record. * @param key reference to a key object. * @return a temporary instance of the value of the corresponding record. * @throw DBM_error if an error occurs or no record corresponds. */ virtual Datum fetchrec(const Datum& key) throw(DBM_error) = 0; /** * Get the first key. * @return a temporary instance of the key of the first record. * @throw DBM_error if an error occurs or no record corresponds. */ virtual Datum firstkey() throw(DBM_error) = 0; /** * Get the next key. * @return a temporary instance of the key of the next record. * @throw DBM_error if an error occurs or no record corresponds. */ virtual Datum nextkey() throw(DBM_error) = 0; /** * Check whether a fatal error occured or not. * @return true if the database has a fatal error, false if not. * @throw DBM_error if an error occurs. */ virtual bool error() throw(DBM_error) = 0; }; #endif /* duplication check */ /* END OF FILE */ qdbm-1.8.78/plus/xcrtest.cc0000644000175000017500000004005410505723450014536 0ustar mikiomikio/************************************************************************************************* * Test cases of Curia for C++ * Copyright (C) 2000-2005 Mikio Hirabayashi * This file is part of QDBM, Quick Database Manager. * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU * Lesser General Public License as published by the Free Software Foundation; either version * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * You should have received a copy of the GNU Lesser General Public License along with QDBM; if * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. *************************************************************************************************/ #include #include #include #include #include #include #include extern "C" { #include #include #include } using namespace std; using namespace qdbm; /* global constants */ const int RECBUFSIZ = 32; const int ALIGNSIZ = 8; const int FBPSIZ = 8; /* struct for closure per thread */ struct Mission { Curia* curia; bool lob; int rnum; int id; bool printer; }; /* global variables */ const char* progname; /* function prototypes */ int main(int argc, char** argv); void myterminate(); void myunexpected(); void usage(); int runwrite(int argc, char** argv); int runread(int argc, char** argv); int runmulti(int argc, char** argv); int runmisc(int argc, char** argv); void pxdperror(const char* name, DBM_error &e); int dowrite(const char* name, int rnum, int bnum, int dnum, bool lob); int doread(const char* name, bool lob); int domulti(const char* name, int rnum, int bnum, int dnum, int tnum, bool lob); void* mtwriter(void* arg); int domisc(const char* name); /* main routine */ int main(int argc, char** argv){ int rv; set_terminate(myterminate); set_unexpected(myunexpected); progname = argv[0]; if(argc < 2) usage(); rv = 0; if(!strcmp(argv[1], "write")){ rv = runwrite(argc, argv); } else if(!strcmp(argv[1], "read")){ rv = runread(argc, argv); } else if(!strcmp(argv[1], "multi")){ rv = runmulti(argc, argv); } else if(!strcmp(argv[1], "misc")){ rv = runmisc(argc, argv); } else { usage(); } return rv; } /* for debug */ void myterminate(){ cout << progname << ": terminate" << endl; exit(1); } /* for debug */ void myunexpected(){ cout << progname << ": unexpected" << endl; exit(1); } /* print the usage and exit */ void usage(){ cerr << progname << ": test cases for Curia for C++" << endl; cerr << endl; cerr << "usage:" << endl; cerr << " " << progname << " write [-lob] name rnum bnum dnum" << endl; cerr << " " << progname << " read [-lob] name" << endl; cerr << " " << progname << " multi [-lob] name rnum bnum dnum tnum" << endl; cerr << " " << progname << " misc name" << endl; cerr << endl; exit(1); } /* parse arguments of write command */ int runwrite(int argc, char** argv){ char *name, *rstr, *bstr, *dstr; int i, rnum, bnum, dnum, rv; bool lob; name = 0; rstr = 0; bstr = 0; dstr = 0; lob = false; for(i = 2; i < argc; i++){ if(argv[i][0] == '-'){ if(!strcmp(argv[i], "-lob")){ lob = true; } else { usage(); } } else if(!name){ name = argv[i]; } else if(!rstr){ rstr = argv[i]; } else if(!bstr){ bstr = argv[i]; } else if(!dstr){ dstr = argv[i]; } else { usage(); } } if(!name || !rstr || !bstr || !dstr) usage(); rnum = atoi(rstr); bnum = atoi(bstr); dnum = atoi(dstr); if(rnum < 1 || bnum < 1 || dnum < 1) usage(); rv = dowrite(name, rnum, bnum, dnum, lob); return rv; } /* parse arguments of read command */ int runread(int argc, char** argv){ char* name; int i, rv; bool lob; name = 0; lob = false; for(i = 2; i < argc; i++){ if(argv[i][0] == '-'){ if(!strcmp(argv[i], "-lob")){ lob = true; } else { usage(); } } else if(!name){ name = argv[i]; } else { usage(); } } if(!name) usage(); rv = doread(name, lob); return rv; } /* parse arguments of multi command */ int runmulti(int argc, char** argv){ char *name, *rstr, *bstr, *dstr, *tstr; int i, rnum, bnum, dnum, tnum, rv; bool lob; name = 0; rstr = 0; bstr = 0; dstr = 0; tstr = 0; lob = false; for(i = 2; i < argc; i++){ if(argv[i][0] == '-'){ if(!strcmp(argv[i], "-lob")){ lob = true; } else { usage(); } } else if(!name){ name = argv[i]; } else if(!rstr){ rstr = argv[i]; } else if(!bstr){ bstr = argv[i]; } else if(!dstr){ dstr = argv[i]; } else if(!tstr){ tstr = argv[i]; } else { usage(); } } if(!name || !rstr || !bstr || !dstr || !tstr) usage(); rnum = atoi(rstr); bnum = atoi(bstr); dnum = atoi(dstr); tnum = atoi(tstr); if(rnum < 1 || bnum < 1 || dnum < 1 || tnum < 1) usage(); rv = domulti(name, rnum, bnum, dnum, tnum, lob); return rv; } /* parse arguments of misc command */ int runmisc(int argc, char** argv){ char* name; int i, rv; name = 0; for(i = 2; i < argc; i++){ if(argv[i][0] == '-'){ usage(); } else if(!name){ name = argv[i]; } else { usage(); } } if(!name) usage(); rv = domisc(name); return rv; } /* print an error message */ void pxdperror(const char* name, DBM_error &e){ cerr << progname << ": " << name << ": " << e << endl; } /* do writing test */ int dowrite(const char* name, int rnum, int bnum, int dnum, bool lob){ int i, len; char buf[RECBUFSIZ]; cout << "" << endl; cout << " name=" << name << " rnum=" << rnum << " bnum=" << bnum << " dnum=" << dnum << " lob=" << lob << endl; cout << endl; Curia* curia = 0; bool err = false; try { // open the database curia = new Curia(name, Curia::OWRITER | Curia::OCREAT | Curia::OTRUNC, bnum, dnum); // roop for storing for(i = 1; i <= rnum; i++){ // set a buffer for a key and a value len = sprintf(buf, "%08d", i); // store a record into the database if(lob){ curia->putlob(buf, len, buf, len); } else { curia->put(buf, len, buf, len); } // print progression if(rnum > 250 && i % (rnum / 250) == 0){ cout << '.'; cout.flush(); if(i == rnum || i % (rnum / 10) == 0){ cout << " (" << setw(8) << setfill('0') << i << ")" << endl; cout.flush(); } } } // close the database curia->close(); cout << "ok" << endl << endl; } catch(Curia_error& e){ err = true; // report an error pxdperror(name, e); } // destroy instance if(curia) delete curia; return err ? 1 : 0; } /* do reading test */ int doread(const char* name, bool lob){ int i, rnum, len; char buf[RECBUFSIZ], *val; cout << "" << endl; cout << " name=" << name << " lob=" << lob << endl; cout << endl; Curia* curia = 0; bool err = false; try { // open the database curia = new Curia(name); // get the number of records if(lob){ rnum = curia->rnumlob(); } else { rnum = curia->rnum(); } // roop for retrieving for(i = 1; i <= rnum; i++){ // set a buffer for a key len = sprintf(buf, "%08d", i); // retrieve a record from the database if(lob){ val = curia->getlob(buf, len); } else { val = curia->get(buf, len); } free(val); // print progression if(rnum > 250 && i % (rnum / 250) == 0){ cout << '.'; cout.flush(); if(i == rnum || i % (rnum / 10) == 0){ cout << " (" << setw(8) << setfill('0') << i << ")" << endl; cout.flush(); } } } // close the database curia->close(); cout << "ok" << endl << endl; } catch(Curia_error& e){ err = true; // report an error pxdperror(name, e); } // destroy instance if(curia) delete curia; return err ? 1 : 0; } /* do multi thread test */ int domulti(const char* name, int rnum, int bnum, int dnum, int tnum, bool lob){ Curia* curia; pthread_t* tids; bool* tsts; Mission* mss; Curia_error* ep; int i, len, size; bool err; char buf[RECBUFSIZ], *val; cout << "" << endl; cout << " name=" << name << " rnum=" << rnum << " bnum=" << bnum << " dnum= " << dnum << " tnum=" << tnum << " lob=" << lob << endl; cout << endl; // open the database curia = 0; try { cout << "Creating a database ... "; curia = new Curia(name, Curia::OWRITER | Curia::OCREAT | Curia::OTRUNC, bnum, dnum); curia->setalign(ALIGNSIZ); curia->setfbpsiz(FBPSIZ); cout << "ok" << endl; } catch(Curia_error& e){ if(curia) delete curia; pxdperror(name, e); return 1; } // prepare threads tids = new pthread_t[tnum]; tsts = new bool[tnum]; mss = new Mission[tnum]; err = false; // roop for each threads cout << "Writing" << endl; for(i = 0; i < tnum; i++){ mss[i].curia = curia; mss[i].lob = lob; mss[i].rnum = rnum; mss[i].id = i; mss[i].printer = (i == tnum / 2); if(pthread_create(tids + i, 0, mtwriter, (void*)(mss + i)) == 0){ tsts[i] = true; } else { tsts[i] = false; err = true; cerr << progname << ": " << name << ": " << "pthread error" << endl; } } // join every threads for(i = 0; i < tnum; i++){ if(tsts[i]){ if(pthread_join(tids[i], (void**)&ep) != 0){ err = true; cerr << progname << ": " << name << ": " << "pthread error" << endl; } } if(ep){ err = true; pxdperror(name, *ep); delete ep; } } delete[] mss; delete[] tsts; delete[] tids; if(!err) cout << "ok" << endl; cout.flush(); // check every record cout << "Validation checking ... "; cout.flush(); try { for(i = 1; i <= rnum; i++){ len = sprintf(buf, "%08d", i); if(lob){ val = curia->getlob(buf, len, 0, -1, &size); } else { val = curia->get(buf, len, 0, -1, &size); } free(val); if(size != tnum){ cerr << progname << ": " << name << ": " << "size error: " << size << endl; err = true; } } } catch(Curia_error& e){ pxdperror(name, e); err = true; } if(!err) cout << "ok" << endl; // close the database cout << "Closing the database ... "; try { curia->close(); } catch(Curia_error& e){ pxdperror(name, e); delete curia; return 1; } cout << "ok" << endl; if(!err) cout << "all ok" << endl << endl; delete curia; return err ? 1 : 0; } /* writer with each thread */ void* mtwriter(void* arg){ Mission* mp = (Mission*)arg; Curia* curia = mp->curia; bool lob = mp->lob; int rnum = mp->rnum; int id = mp->id; bool printer = mp->printer; char buf[RECBUFSIZ]; void* mc; int i, len; // roop for storing for(i = 1; i <= rnum; i++){ len = sprintf(buf, "%08d", i); // store a record try { if(lob){ curia->putlob(buf, len, id % 2 ? "*" : "=", 1, Curia::DCAT); } else { curia->put(buf, len, id % 2 ? "*" : "=", 1, Curia::DCAT); } } catch(Curia_error& e){ return new Curia_error(e); } // print progression if(printer && rnum > 250 && i % (rnum / 250) == 0){ cout << '.'; cout.flush(); if(i == rnum || i % (rnum / 10) == 0){ cout << " (" << setw(8) << setfill('0') << i << ")" << endl; cout.flush(); } } // malloc reentrant check if((mc = (char*)malloc(1)) != 0){ free(mc); } else { return new Curia_error(Curia::EALLOC); } } return 0; } /* do combination test */ int domisc(const char* name){ bool err; int i, len; char buf[RECBUFSIZ], *tmp; cout << "" << endl; cout << " name=" << name << endl; cout << endl; err = false; ADBM* adbm = 0; try { // open the database cout << "Creating a database ... "; adbm = new Curia(name, Curia::OWRITER | Curia::OCREAT | Curia::OTRUNC); cout << "ok" << endl; // write with datadase abstraction cout << "Writing with database abstraction ... "; for(i = 1; i <= 100; i++){ len = sprintf(buf, "%08d", i); Datum key(buf, len); Datum val(buf, len); adbm->storerec(key, val, true); } cout << "ok" << endl; // read with datadase abstraction cout << "Reading with database abstraction ... "; for(i = 1; i <= 100; i++){ len = sprintf(buf, "%08d", i); Datum key(buf, len); const Datum& val = adbm->fetchrec(key); len = val.size(); if(len != 8) throw DBM_error("size error"); } cout << "ok" << endl; // traversal access with database abstraction cout << "Traversal access with database abstraction ... "; i = 0; try { for(adbm->firstkey(); true; adbm->nextkey()){ i++; } } catch(DBM_error& e){ if(adbm->error()) throw; } if(i != 100) throw DBM_error("iteration error"); cout << "ok" << endl; // close the database cout << "Closing the database ... "; adbm->close(); cout << "ok" << endl; } catch(DBM_error& e){ err = true; pxdperror(name, e); } if(adbm) delete adbm; if(err) return 1; Curia* curia = 0; try { // open the database cout << "Opening the database ... "; curia = new Curia(name); cout << "ok" << endl; // traversal access cout << "Traversal access ... "; try { curia->iterinit(); for(i = 0; true; i++){ free(curia->iternext(0)); } if(i != 100) throw Curia_error(); } catch(Curia_error& e){ if(e != Curia::ENOITEM) throw; } cout << "ok" << endl; // checking information cout << "Checking information" << endl; cout << " - fsiz ... " << curia->fsiz() << endl; cout << " - bnum ... " << curia->bnum() << endl; cout << " - busenum ... " << curia->busenum() << endl; cout << " - rnum ... " << curia->rnum() << endl; cout << " - writable ... " << curia->writable() << endl; cout << " - fatalerror ... " << curia->fatalerror() << endl; cout << " - inode ... " << curia->inode() << endl; cout << " - mtime ... " << curia->mtime() << endl; cout << "ok" << endl; // close the database cout << "Closing the database ... "; curia->close(); cout << "ok" << endl; } catch(Curia_error& e){ err = true; pxdperror(name, e); } if(curia) delete curia; if(err) return 1; curia = 0; try { // open the database cout << "Opening the database ... "; curia = new Curia(name, Curia::OWRITER); curia->silent = true; cout << "ok" << endl; // sync the database cout << "Syncing the database ... "; curia->sync(); cout << "ok" << endl; // optimize the database cout << "Optimizing the database ... "; curia->optimize(); cout << "ok" << endl; // write in silent mode cout << "Writing in silent mode ... "; for(i = 1; i <= 100; i++){ len = sprintf(buf, "%d", rand() % 100); curia->put(buf, len, buf, len, Curia::DKEEP); } cout << "ok" << endl; // read in silent mode cout << "Reading in silent mode ... "; for(i = 1; i <= 100; i++){ len = sprintf(buf, "%d", rand() % 100); if((tmp = curia->get(buf, len)) != 0) free(tmp); } cout << "ok" << endl; // traversal access cout << "Traversal access in silent mode ... "; curia->iterinit(); while((tmp = curia->iternext()) != 0){ free(tmp); } cout << "ok" << endl; // close the database cout << "Closing the database ... "; curia->close(); cout << "ok" << endl; } catch(Curia_error& e){ err = true; pxdperror(name, e); } if(curia) delete curia; if(err) return 1; cout << "all ok" << endl << endl; return 0; } /* END OF FILE */ qdbm-1.8.78/plus/xdptest.cc0000644000175000017500000003537710505723426014554 0ustar mikiomikio/************************************************************************************************* * Test cases of Depot for C++ * Copyright (C) 2000-2005 Mikio Hirabayashi * This file is part of QDBM, Quick Database Manager. * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU * Lesser General Public License as published by the Free Software Foundation; either version * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * You should have received a copy of the GNU Lesser General Public License along with QDBM; if * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. *************************************************************************************************/ #include #include #include #include #include #include #include extern "C" { #include #include #include } using namespace std; using namespace qdbm; /* global constants */ const int RECBUFSIZ = 32; const int ALIGNSIZ = 8; const int FBPSIZ = 8; /* struct for closure per thread */ struct Mission { Depot* depot; int rnum; int id; bool printer; }; /* global variables */ const char* progname; /* function prototypes */ int main(int argc, char** argv); void myterminate(); void myunexpected(); void usage(); int runwrite(int argc, char** argv); int runread(int argc, char** argv); int runmulti(int argc, char** argv); int runmisc(int argc, char** argv); void pxdperror(const char* name, DBM_error &e); int dowrite(const char* name, int rnum, int bnum); int doread(const char* name); int domulti(const char* name, int rnum, int bnum, int tnum); void* mtwriter(void* arg); int domisc(const char* name); /* main routine */ int main(int argc, char** argv){ int rv; set_terminate(myterminate); set_unexpected(myunexpected); progname = argv[0]; if(argc < 2) usage(); rv = 0; if(!strcmp(argv[1], "write")){ rv = runwrite(argc, argv); } else if(!strcmp(argv[1], "read")){ rv = runread(argc, argv); } else if(!strcmp(argv[1], "multi")){ rv = runmulti(argc, argv); } else if(!strcmp(argv[1], "misc")){ rv = runmisc(argc, argv); } else { usage(); } return rv; } /* for debug */ void myterminate(){ cout << progname << ": terminate" << endl; exit(1); } /* for debug */ void myunexpected(){ cout << progname << ": unexpected" << endl; exit(1); } /* print the usage and exit */ void usage(){ cerr << progname << ": test cases for Depot for C++" << endl; cerr << endl; cerr << "usage:" << endl; cerr << " " << progname << " write name rnum bnum" << endl; cerr << " " << progname << " read name" << endl; cerr << " " << progname << " multi name rnum bnum tnum" << endl; cerr << " " << progname << " misc name" << endl; cerr << endl; exit(1); } /* parse arguments of write command */ int runwrite(int argc, char** argv){ char *name, *rstr, *bstr; int i, rnum, bnum, rv; name = 0; rstr = 0; bstr = 0; for(i = 2; i < argc; i++){ if(argv[i][0] == '-'){ usage(); } else if(!name){ name = argv[i]; } else if(!rstr){ rstr = argv[i]; } else if(!bstr){ bstr = argv[i]; } else { usage(); } } if(!name || !rstr || !bstr) usage(); rnum = atoi(rstr); bnum = atoi(bstr); if(rnum < 1 || bnum < 1) usage(); rv = dowrite(name, rnum, bnum); return rv; } /* parse arguments of read command */ int runread(int argc, char** argv){ char* name; int i, rv; name = 0; for(i = 2; i < argc; i++){ if(argv[i][0] == '-'){ usage(); } else if(!name){ name = argv[i]; } else { usage(); } } if(!name) usage(); rv = doread(name); return rv; } /* parse arguments of multi command */ int runmulti(int argc, char** argv){ char *name, *rstr, *bstr, *tstr; int i, rnum, bnum, tnum, rv; name = 0; rstr = 0; bstr = 0; tstr = 0; for(i = 2; i < argc; i++){ if(argv[i][0] == '-'){ usage(); } else if(!name){ name = argv[i]; } else if(!rstr){ rstr = argv[i]; } else if(!bstr){ bstr = argv[i]; } else if(!tstr){ tstr = argv[i]; } else { usage(); } } if(!name || !rstr || !bstr || !tstr) usage(); rnum = atoi(rstr); bnum = atoi(bstr); tnum = atoi(tstr); if(rnum < 1 || bnum < 1 || tnum < 1) usage(); rv = domulti(name, rnum, bnum, tnum); return rv; } /* parse arguments of misc command */ int runmisc(int argc, char** argv){ char* name; int i, rv; name = 0; for(i = 2; i < argc; i++){ if(argv[i][0] == '-'){ usage(); } else if(!name){ name = argv[i]; } else { usage(); } } if(!name) usage(); rv = domisc(name); return rv; } /* print an error message */ void pxdperror(const char* name, DBM_error &e){ cerr << progname << ": " << name << ": " << e << endl; } /* do writing test */ int dowrite(const char* name, int rnum, int bnum){ int i, len; char buf[RECBUFSIZ]; cout << "" << endl; cout << " name=" << name << " rnum=" << rnum << " bnum=" << bnum << endl; cout << endl; Depot* depot = 0; bool err = false; try { // open the database depot = new Depot(name, Depot::OWRITER | Depot::OCREAT | Depot::OTRUNC, bnum); // roop for storing for(i = 1; i <= rnum; i++){ // set a buffer for a key and a value len = sprintf(buf, "%08d", i); // store a record into the database depot->put(buf, len, buf, len); // print progression if(rnum > 250 && i % (rnum / 250) == 0){ cout << '.'; cout.flush(); if(i == rnum || i % (rnum / 10) == 0){ cout << " (" << setw(8) << setfill('0') << i << ")" << endl; cout.flush(); } } } // close the database depot->close(); cout << "ok" << endl << endl; } catch(Depot_error& e){ err = true; // report an error pxdperror(name, e); } // destroy instance if(depot) delete depot; return err ? 1 : 0; } /* do reading test */ int doread(const char* name){ int i, rnum, len; char buf[RECBUFSIZ], *val; cout << "" << endl; cout << " name=" << name << endl; cout << endl; Depot* depot = 0; bool err = false; try { // open the database depot = new Depot(name); // get the number of records rnum = depot->rnum(); // roop for retrieving for(i = 1; i <= rnum; i++){ // set a buffer for a key len = sprintf(buf, "%08d", i); // retrieve a record from the database val = depot->get(buf, len); free(val); // print progression if(rnum > 250 && i % (rnum / 250) == 0){ cout << '.'; cout.flush(); if(i == rnum || i % (rnum / 10) == 0){ cout << " (" << setw(8) << setfill('0') << i << ")" << endl; cout.flush(); } } } // close the database depot->close(); cout << "ok" << endl << endl; } catch(Depot_error& e){ err = true; // report an error pxdperror(name, e); } // destroy instance if(depot) delete depot; return err ? 1 : 0; } /* do multi thread test */ int domulti(const char* name, int rnum, int bnum, int tnum){ Depot* depot; pthread_t* tids; bool* tsts; Mission* mss; Depot_error* ep; int i, len, size; bool err; char buf[RECBUFSIZ], *val; cout << "" << endl; cout << " name=" << name << " rnum=" << rnum << " bnum=" << bnum << " tnum=" << tnum << endl; cout << endl; // open the database depot = 0; try { cout << "Creating a database ... "; depot = new Depot(name, Depot::OWRITER | Depot::OCREAT | Depot::OTRUNC, bnum); depot->setalign(ALIGNSIZ); depot->setfbpsiz(FBPSIZ); cout << "ok" << endl; } catch(Depot_error& e){ if(depot) delete depot; pxdperror(name, e); return 1; } // prepare threads tids = new pthread_t[tnum]; tsts = new bool[tnum]; mss = new Mission[tnum]; err = false; // roop for each threads cout << "Writing" << endl; for(i = 0; i < tnum; i++){ mss[i].depot = depot; mss[i].rnum = rnum; mss[i].id = i; mss[i].printer = (i == tnum / 2); if(pthread_create(tids + i, 0, mtwriter, (void*)(mss + i)) == 0){ tsts[i] = true; } else { tsts[i] = false; err = true; cerr << progname << ": " << name << ": " << "pthread error" << endl; } } // join every threads for(i = 0; i < tnum; i++){ if(tsts[i]){ if(pthread_join(tids[i], (void**)&ep) != 0){ err = true; cerr << progname << ": " << name << ": " << "pthread error" << endl; } } if(ep){ err = true; pxdperror(name, *ep); delete ep; } } delete[] mss; delete[] tsts; delete[] tids; if(!err) cout << "ok" << endl; cout.flush(); // check every record cout << "Validation checking ... "; try { for(i = 1; i <= rnum; i++){ len = sprintf(buf, "%08d", i); val = depot->get(buf, len, 0, -1, &size); free(val); if(size != tnum){ cerr << progname << ": " << name << ": " << "size error: " << size << endl; err = true; } } } catch(Depot_error& e){ pxdperror(name, e); err = true; } if(!err) cout << "ok" << endl; // close the database cout << "Closing the database ... "; try { depot->close(); } catch(Depot_error& e){ pxdperror(name, e); delete depot; return 1; } cout << "ok" << endl; if(!err) cout << "all ok" << endl << endl; delete depot; return err ? 1 : 0; } /* writer with each thread */ void* mtwriter(void* arg){ Mission* mp = (Mission*)arg; Depot* depot = mp->depot; int rnum = mp->rnum; int id = mp->id; bool printer = mp->printer; char buf[RECBUFSIZ]; void* mc; int i, len; // roop for storing for(i = 1; i <= rnum; i++){ len = sprintf(buf, "%08d", i); // store a record try { depot->put(buf, len, id % 2 ? "*" : "=", 1, Depot::DCAT); } catch(Depot_error& e){ return new Depot_error(e); } // print progression if(printer && rnum > 250 && i % (rnum / 250) == 0){ cout << '.'; cout.flush(); if(i == rnum || i % (rnum / 10) == 0){ cout << " (" << setw(8) << setfill('0') << i << ")" << endl; cout.flush(); } } // malloc reentrant check if((mc = (char*)malloc(1)) != 0){ free(mc); } else { return new Depot_error(Depot::EALLOC); } } return 0; } /* do combination test */ int domisc(const char* name){ bool err; int i, len; char buf[RECBUFSIZ], *tmp; cout << "" << endl; cout << " name=" << name << endl; cout << endl; err = false; ADBM* adbm = 0; try { // open the database cout << "Creating a database ... "; adbm = new Depot(name, Depot::OWRITER | Depot::OCREAT | Depot::OTRUNC); cout << "ok" << endl; // write with datadase abstraction cout << "Writing with database abstraction ... "; for(i = 1; i <= 100; i++){ len = sprintf(buf, "%08d", i); Datum key(buf, len); Datum val(buf, len); adbm->storerec(key, val, true); } cout << "ok" << endl; // read with datadase abstraction cout << "Reading with database abstraction ... "; for(i = 1; i <= 100; i++){ len = sprintf(buf, "%08d", i); Datum key(buf, len); const Datum& val = adbm->fetchrec(key); len = val.size(); if(len != 8) throw DBM_error("size error"); } cout << "ok" << endl; // traversal access with database abstraction cout << "Traversal access with database abstraction ... "; i = 0; try { for(adbm->firstkey(); true; adbm->nextkey()){ i++; } } catch(DBM_error& e){ if(adbm->error()) throw; } if(i != 100) throw DBM_error("iteration error"); cout << "ok" << endl; // close the database cout << "Closing the database ... "; adbm->close(); cout << "ok" << endl; } catch(DBM_error& e){ err = true; pxdperror(name, e); } if(adbm) delete adbm; if(err) return 1; Depot* depot = 0; try { // open the database cout << "Opening the database ... "; depot = new Depot(name); cout << "ok" << endl; // traversal access cout << "Traversal access ... "; try { depot->iterinit(); for(i = 0; true; i++){ free(depot->iternext(0)); } if(i != 100) throw Depot_error(); } catch(Depot_error& e){ if(e != Depot::ENOITEM) throw; } cout << "ok" << endl; // checking information cout << "Checking information" << endl; cout << " - fsiz ... " << depot->fsiz() << endl; cout << " - bnum ... " << depot->bnum() << endl; cout << " - busenum ... " << depot->busenum() << endl; cout << " - rnum ... " << depot->rnum() << endl; cout << " - writable ... " << depot->writable() << endl; cout << " - fatalerror ... " << depot->fatalerror() << endl; cout << " - inode ... " << depot->inode() << endl; cout << " - mtime ... " << depot->mtime() << endl; cout << "ok" << endl; // close the database cout << "Closing the database ... "; depot->close(); cout << "ok" << endl; } catch(Depot_error& e){ err = true; pxdperror(name, e); } if(depot) delete depot; if(err) return 1; depot = 0; try { // open the database cout << "Opening the database ... "; depot = new Depot(name, Depot::OWRITER); depot->silent = true; cout << "ok" << endl; // sync the database cout << "Syncing the database ... "; depot->sync(); cout << "ok" << endl; // optimize the database cout << "Optimizing the database ... "; depot->optimize(); cout << "ok" << endl; // write in silent mode cout << "Writing in silent mode ... "; for(i = 1; i <= 100; i++){ len = sprintf(buf, "%d", rand() % 100); depot->put(buf, len, buf, len, Depot::DKEEP); } cout << "ok" << endl; // read in silent mode cout << "Reading in silent mode ... "; for(i = 1; i <= 100; i++){ len = sprintf(buf, "%d", rand() % 100); if((tmp = depot->get(buf, len)) != 0) free(tmp); } cout << "ok" << endl; // traversal access cout << "Traversal access in silent mode ... "; depot->iterinit(); while((tmp = depot->iternext()) != 0){ free(tmp); } cout << "ok" << endl; // close the database cout << "Closing the database ... "; depot->close(); cout << "ok" << endl; } catch(Depot_error& e){ err = true; pxdperror(name, e); } if(depot) delete depot; if(err) return 1; cout << "all ok" << endl << endl; return 0; } /* END OF FILE */ qdbm-1.8.78/plus/xdepot.h0000644000175000017500000005443610505721637014225 0ustar mikiomikio/************************************************************************************************* * C++ API of Depot, the basic API of QDBM * Copyright (C) 2000-2006 Mikio Hirabayashi * This file is part of QDBM, Quick Database Manager. * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU * Lesser General Public License as published by the Free Software Foundation; either version * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * You should have received a copy of the GNU Lesser General Public License along with QDBM; if * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. *************************************************************************************************/ #ifndef _XDEPOT_H /* duplication check */ #define _XDEPOT_H #include #include extern "C" { #include #include #include } /** * Error container for Depot. */ class qdbm::Depot_error : public virtual DBM_error { //---------------------------------------------------------------- // public member functions //---------------------------------------------------------------- public: /** * Create an instance. */ Depot_error() throw(); /** * Create an instance. * @param ecode the error code. */ Depot_error(int ecode) throw(); /** * Copy constructor. * @param de a source instance. */ Depot_error(const Depot_error& de) throw(); /** * Release resources of the instance. */ virtual ~Depot_error() throw(); /** * Assignment operator. * @param de a source instance. * @return reference to itself. */ Depot_error& operator =(const Depot_error& de) throw(); /** * Assignment operator. * @param ecode the error code. * @return reference to itself. */ Depot_error& operator =(int ecode) throw(); /** * Equality operator. * @param de a comparing instance. * @return true if both equal, else, false. */ virtual bool operator ==(const Depot_error& de) const throw(); /** * Inequality operator. * @param de a comparing instance. * @return true if both do not equal, else, false. */ virtual bool operator !=(const Depot_error& de) const throw(); /** * Equality operator. * @param ecode a comparing error code. * @return true if both equal, else, false. */ virtual bool operator ==(int ecode) const throw(); /** * Inequality operator. * @param ecode a comparing error code. * @return true if both do not equal, else, false. */ virtual bool operator !=(int ecode) const throw(); /** * Cast operator into pointer to char. * @return the pointer to the string. */ virtual operator const char*() const throw(); /** * Get the error code. * @return the error code. */ virtual int code() const throw(); /** * Get the error message. * @return the pointer to the string. */ virtual const char* message() const throw(); //---------------------------------------------------------------- // private member variables //---------------------------------------------------------------- private: /** The error code. */ int ecode; }; /** * C++ API of Depot, the basic API of QDBM. */ class qdbm::Depot : public virtual ADBM { //---------------------------------------------------------------- // public static member constants //---------------------------------------------------------------- public: static const int ENOERR; ///< error code: no error static const int EFATAL; ///< error code: with fatal error static const int EMODE; ///< error code: invalid mode static const int EBROKEN; ///< error code: broken database file static const int EKEEP; ///< error code: existing record static const int ENOITEM; ///< error code: no item found static const int EALLOC; ///< error code: memory allocation error static const int EMAP; ///< error code: memory mapping error static const int EOPEN; ///< error code: open error static const int ECLOSE; ///< error code: close error static const int ETRUNC; ///< error code: trunc error static const int ESYNC; ///< error code: sync error static const int ESTAT; ///< error code: stat error static const int ESEEK; ///< error code: seek error static const int EREAD; ///< error code: read error static const int EWRITE; ///< error code: write error static const int ELOCK; ///< error code: lock error static const int EUNLINK; ///< error code: unlink error static const int EMKDIR; ///< error code: mkdir error static const int ERMDIR; ///< error code: rmdir error static const int EMISC; ///< error code: miscellaneous error static const int OREADER; ///< open mode: open as a reader static const int OWRITER; ///< open mode: open as a writer static const int OCREAT; ///< open mode: writer creating static const int OTRUNC; ///< open mode: writer truncating static const int ONOLCK; ///< open mode: open without locking static const int OLCKNB; ///< open mode: lock without blocking static const int OSPARSE; ///< open mode: create as a sparse file static const int DOVER; ///< write mode: overwrite the existing value static const int DKEEP; ///< write mode: keep the existing value static const int DCAT; ///< write mode: concatenate values //---------------------------------------------------------------- // public static member functions //---------------------------------------------------------------- public: /** * Get the version information. * @return the string of the version information. */ static const char* version() throw(); /** * Remove a database file. * @param name the name of a database file. * @throw Depot_error if an error occurs. */ static void remove(const char* name) throw(Depot_error); /** * Retrieve a record directly from a database file. * @param name the name of a database file. * @param kbuf the pointer to the region of a key. * @param ksiz the size of the region of the key. If it is negative, the size is assigned * with `std::strlen(kbuf)'. * @param sp the pointer to a variable to which the size of the region of the return value * is assigned. If it is 0, it is not used. * @return the pointer to the region of the value of the corresponding record. * @throw Depot_error if an error occurs or no record corresponds. * @note Because an additional zero code is appended at the end of the region of the return * value, the return value can be treated as a character string. Because the region of the * return value is allocated with the `std::malloc' call, it should be released with the * `std::free' call if it is no longer in use. Although this method can be used even while * the database file is locked by another process, it is not assured that recent updated is * reflected. */ static char* snaffle(const char* name, const char* kbuf, int ksiz, int* sp) throw(Depot_error); //---------------------------------------------------------------- // public member functions //---------------------------------------------------------------- public: /** * Get the database handle. * @param name the name of a database file. * @param omode the connection mode: `Depot::OWRITER' as a writer, `Depot::OREADER' as * a reader. If the mode is `Depot::OWRITER', the following may be added by bitwise or: * `Depot::OCREAT', which means it creates a new database if not exist, `Depot::OTRUNC', * which means it creates a new database regardless if one exists. Both of `Depot::OREADER' * and `Depot::OWRITER' can be added to by bitwise or: `Depot::ONOLCK', which means it opens a * database file without file locking, or `Depot::OLCKNB', which means locking is performed * without blocking. `Depot::OCREAT' can be added to by bitwise or: `Depot::OSPARSE', which * means it creates a database file as a sparse file. * @param bnum the number of elements of the bucket array. If it is not more than 0, * the default value is specified. The size of a bucket array is determined on creating, * and can not be changed except for by optimization of the database. Suggested size of a * bucket array is about from 0.5 to 4 times of the number of all records to store. * @throw Depot_error if an error occurs. * @note While connecting as a writer, an exclusive lock is invoked to the database file. * While connecting as a reader, a shared lock is invoked to the database file. The thread * blocks until the lock is achieved. If `Depot::ONOLCK' is used, the application is * responsible for exclusion control. */ Depot(const char* name, int omode = Depot::OREADER, int bnum = -1) throw(Depot_error); /** * Release the resources. * @note If the database handle is not closed yet, it is closed. */ virtual ~Depot() throw(); /** * Close the database handle. * @throw Depot_error if an error occurs. * @note Updating a database is assured to be written when the handle is closed. If a writer * opens a database but does not close it appropriately, the database will be broken. */ virtual void close() throw(Depot_error); /** * Store a record. * @param kbuf the pointer to the region of a key. * @param ksiz the size of the region of the key. If it is negative, the size is assigned * with `std::strlen(kbuf)'. * @param vbuf the pointer to the region of a value. * @param vsiz the size of the region of the value. If it is negative, the size is assigned * with `std::strlen(vbuf)'. * @param dmode behavior when the key overlaps, by the following values: `Depot::DOVER', * which means the specified value overwrites the existing one, `Depot::DKEEP', which means the * existing value is kept, `Depot::DCAT', which means the specified value is concatenated at * the end of the existing value. * @return always true. However, if the silent flag is true and replace is cancelled, false is * returned instead of exception. * @throw Depot_error if an error occurs or replace is cancelled. */ virtual bool put(const char* kbuf, int ksiz, const char* vbuf, int vsiz, int dmode = Depot::DOVER) throw(Depot_error); /** * Delete a record. * @param kbuf the pointer to the region of a key. * @param ksiz the size of the region of the key. If it is negative, the size is assigned * with `std::strlen(kbuf)'. * @return always true. However, if the silent flag is true and no record corresponds, false * is returned instead of exception. * @throw Depot_error if an error occurs or no record corresponds. */ virtual bool out(const char* kbuf, int ksiz) throw(Depot_error); /** * Retrieve a record. * @param kbuf the pointer to the region of a key. * @param ksiz the size of the region of the key. If it is negative, the size is assigned * with `std::strlen(kbuf)'. * @param start the offset address of the beginning of the region of the value to be read. * @param max the max size to read with. If it is negative, the size is unlimited. * @param sp the pointer to a variable to which the size of the region of the return value * is assigned. If it is 0, it is not used. * @return the pointer to the region of the value of the corresponding record. If the silent * flag is true and no record corresponds, 0 is returned instead of exception. * @throw Depot_error if an error occurs, no record corresponds, or the size of the value * of the corresponding record is less than `start'. * @note Because an additional zero code is appended at the end of the region of the return * value, the return value can be treated as a character string. Because the region of the * return value is allocated with the `std::malloc' call, it should be released with the * `std::free' call if it is no longer in use. */ virtual char* get(const char* kbuf, int ksiz, int start = 0, int max = -1, int* sp = 0) throw(Depot_error); /** * Retrieve a record and write the value into a buffer. * @param kbuf the pointer to the region of a key. * @param ksiz the size of the region of the key. If it is negative, the size is assigned * with `std::strlen(kbuf)'. * @param start the offset address of the beginning of the region of the value to be read. * @param max the max size to be read. It shuld be equal to or less than the size of the * writing buffer. * @param vbuf the pointer to a buffer into which the value of the corresponding record is * written. * @return the return value is the size of the written data. If the silent flag is true and * no record corresponds, -1 is returned instead of exception. * @throw Depot_error if an error occurs, no record corresponds, or the size of the value * of the corresponding record is less than `start'. * @note No additional zero code is appended at the end of the region of the writing buffer. */ virtual int getwb(const char *kbuf, int ksiz, int start, int max, char *vbuf) throw(Depot_error); /** * Get the size of the value of a record. * @param kbuf the pointer to the region of a key. * @param ksiz the size of the region of the key. If it is negative, the size is assigned * with `std::strlen(kbuf)'. * @return the size of the value of the corresponding record. If the silent flag is true and * no record corresponds, -1 is returned instead of exception. * @throw Depot_error if an error occurs or no record corresponds. * @note Because this function does not read the entity of a record, it is faster than `get'. */ virtual int vsiz(const char* kbuf, int ksiz) throw(Depot_error); /** * Initialize the iterator of the database handle. * @throw Depot_error if an error occurs. * @note The iterator is used in order to access the key of every record stored in a database. */ virtual void iterinit() throw(Depot_error); /** * Get the next key of the iterator. * @param sp the pointer to a variable to which the size of the region of the return value * is assigned. If it is 0, it is not used. * @return the pointer to the region of the next key. If the silent flag is true and no record * corresponds, 0 is returned instead of exception. * @throw Depot_error if an error occurs or no record is to be get out of the iterator. * @note Because an additional zero code is appended at the end of the region of the return * value, the return value can be treated as a character string. Because the region of the * return value is allocated with the `std::malloc' call, it should be released with the * `std::free' call if it is no longer in use. It is possible to access every record by * iteration of calling this function. However, it is not assured if updating the database * is occurred while the iteration. Besides, the order of this traversal access method is * arbitrary, so it is not assured that the order of storing matches the one of the traversal * access. */ virtual char* iternext(int* sp = 0) throw(Depot_error); /** * Set alignment of the database handle. * @param align the basic size of alignment. * @throw Depot_error if an error occurs. * @note If alignment is set to a database, the efficiency of overwriting values is improved. * The size of alignment is suggested to be average size of the values of the records to be * stored. If alignment is positive, padding whose size is multiple number of the alignment * is placed. If alignment is negative, as `vsiz' is the size of a value, the size of padding * is calculated with `(vsiz / pow(2, abs(align) - 1))'. Because alignment setting is not * saved in a database, you should specify alignment every opening a database. */ virtual void setalign(int align) throw(Depot_error); /** * Set the size of the free block pool. * @param size the size of the free block pool of a database. * @throw Depot_error if an error occurs. * @note The default size of the free block pool is 16. If the size is greater, the space * efficiency of overwriting values is improved with the time efficiency sacrificed. */ virtual void setfbpsiz(int size) throw(Depot_error); /** * Synchronize updating contents with the file and the device. * @throw Depot_error if an error occurs. * @note This function is useful when another process uses the connected database file. */ virtual void sync() throw(Depot_error); /** * Optimize the database. * @param bnum the number of the elements of the bucket array. If it is not more than 0, * the default value is specified. * @throw Depot_error if an error occurs. * @note In an alternating succession of deleting and storing with overwrite or concatenate, * dispensable regions accumulate. This function is useful to do away with them. */ virtual void optimize(int bnum = -1) throw(Depot_error); /** * Get the name of the database. * @return the pointer to the region of the name of the database. * @throw Depot_error if an error occurs. * @note Because the region of the return value is allocated with the `std::malloc' call, * it should be released with the `std::free' call if it is no longer in use. */ virtual char* name() throw(Depot_error); /** * Get the size of the database file. * @return the size of the database file. * @throw Depot_error if an error occurs. */ virtual int fsiz() throw(Depot_error); /** * Get the number of the elements of the bucket array. * @return the number of the elements of the bucket array. * @throw Depot_error if an error occurs. */ virtual int bnum() throw(Depot_error); /** * Get the number of the used elements of the bucket array. * @return the number of the used elements of the bucket array. * @throw Depot_error if an error occurs. * @note This function is inefficient because it accesses all elements of the bucket array. */ virtual int busenum() throw(Depot_error); /** * Get the number of the records stored in the database. * @return the number of the records stored in the database. * @throw Depot_error if an error occurs. */ virtual int rnum() throw(Depot_error); /** * Check whether the database handle is a writer or not. * @return true if the handle is a writer, false if not. * @throw Depot_error if an error occurs. */ virtual bool writable() throw(Depot_error); /** * Check whether the database has a fatal error or not. * @return true if the database has a fatal error, false if not. * @throw Depot_error if an error occurs. */ virtual bool fatalerror() throw(Depot_error); /** * Get the inode number of the database file. * @return the inode number of the database file. * @throw Depot_error if an error occurs. */ virtual int inode() throw(Depot_error); /** * Get the last modified time of the database. * @return the last modified time the database. * @throw Depot_error if an error occurs. */ virtual time_t mtime() throw(Depot_error); /** * Get the file descriptor of the database file. * @return the file descriptor of the database file. * @throw Depot_error if an error occurs. * @note Handling the file descriptor of a database file directly is not suggested. */ virtual int fdesc() throw(Depot_error); /** * Store a record. * @param key reference to a key object. * @param val reference to a value object. * @param replace whether the existing value is to be overwritten or not. * @throw Depot_error if an error occurs or replace is cancelled. */ virtual void storerec(const Datum& key, const Datum& val, bool replace = true) throw(Depot_error); /** * Delete a record. * @param key reference to a key object. * @throw Depot_error if an error occurs or no record corresponds. */ virtual void deleterec(const Datum& key) throw(Depot_error); /** * Fetch a record. * @param key reference to a key object. * @return a temporary instance of the value of the corresponding record. * @throw Depot_error if an error occurs or no record corresponds. */ virtual Datum fetchrec(const Datum& key) throw(Depot_error); /** * Get the first key. * @return a temporary instance of the key of the first record. * @throw Depot_error if an error occurs or no record corresponds. */ virtual Datum firstkey() throw(Depot_error); /** * Get the next key. * @return a temporary instance of the key of the next record. * @throw Depot_error if an error occurs or no record corresponds. */ virtual Datum nextkey() throw(Depot_error); /** * Check whether a fatal error occured or not. * @return true if the database has a fatal error, false if not. * @throw Depot_error if an error occurs. */ virtual bool error() throw(Depot_error); //---------------------------------------------------------------- // public member variables //---------------------------------------------------------------- public: bool silent; ///< whether to repress frequent exceptions //---------------------------------------------------------------- // private member variables //---------------------------------------------------------------- private: DEPOT* depot; ///< internal database handle pthread_mutex_t mymutex; ///< internal mutex //---------------------------------------------------------------- // private member functions //---------------------------------------------------------------- private: /** copy constructor: This should not be used. */ Depot(const Depot& depot) throw(Depot_error); /** assignment operator: This should not be used. */ Depot& operator =(const Depot& depot) throw(Depot_error); /** lock the database. */ bool lock(); /** unlock the database. */ void unlock(); }; #endif /* duplication check */ /* END OF FILE */ qdbm-1.8.78/plus/Doxyfile0000644000175000017500000000212410572737731014250 0ustar mikiomikio# Doxyfile for C++ API of QDBM # General configuration options PROJECT_NAME = "QDBM for C++" OUTPUT_LANGUAGE = English EXTRACT_ALL = NO EXTRACT_PRIVATE = NO EXTRACT_STATIC = NO SHOW_INCLUDE_FILES = NO VERBATIM_HEADERS = NO JAVADOC_AUTOBRIEF = YES DETAILS_AT_TOP = YES INLINE_INFO = NO OPTIMIZE_OUTPUT_FOR_C = NO OPTIMIZE_OUTPUT_JAVA = NO QUIET = YES WARNINGS = YES # Configuration options related to the input files INPUT = . FILE_PATTERNS = overview xqdbm.h xadbm.h xdepot.h xcuria.h xvilla.h RECURSIVE = NO # Configuration options related to the HTML output GENERATE_HTML = YES HTML_OUTPUT = xapidoc HTML_FILE_EXTENSION = .html GENERATE_TREEVIEW = YES TREEVIEW_WIDTH = 250 # Configuration options related to the LaTeX output GENERATE_LATEX = NO LATEX_OUTPUT = latex # Configuration options related to the man page output GENERATE_MAN = NO MAN_OUTPUT = man MAN_EXTENSION = .3 # Configuration options related to the dot tool #HAVE_DOT = YES #CLASS_GRAPH = YES #COLLABORATION_GRAPH = NO #INCLUDE_GRAPH = NO #INCLUDED_BY_GRAPH = NO #GRAPHICAL_HIERARCHY = YES #GENERATE_LEGEND = NO # END OF FILE qdbm-1.8.78/plus/configure0000755000175000017500000037114311426320060014441 0ustar mikiomikio#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.65 for qdbm-plus 1.0.0. # # # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, # 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, # Inc. # # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi " as_required="as_fn_return () { (exit \$1); } as_fn_success () { as_fn_return 0; } as_fn_failure () { as_fn_return 1; } as_fn_ret_success () { return 0; } as_fn_ret_failure () { return 1; } exitcode=0 as_fn_success || { exitcode=1; echo as_fn_success failed.; } as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : else exitcode=1; echo positional parameters were not saved. fi test x\$exitcode = x0 || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1" if (eval "$as_required") 2>/dev/null; then : as_have_required=yes else as_have_required=no fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. as_shell=$as_dir/$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : CONFIG_SHELL=$as_shell as_have_required=yes if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : break 2 fi fi done;; esac as_found=false done $as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : CONFIG_SHELL=$SHELL as_have_required=yes fi; } IFS=$as_save_IFS if test "x$CONFIG_SHELL" != x; then : # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV export CONFIG_SHELL exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"} fi if test x$as_have_required = xno; then : $as_echo "$0: This script requires a shell more modern than all" $as_echo "$0: the shells that I found on your system." if test x${ZSH_VERSION+set} = xset ; then $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" $as_echo "$0: be upgraded to zsh 4.3.4 or later." else $as_echo "$0: Please tell bug-autoconf@gnu.org about your system, $0: including any error possibly output before this $0: message. Then install a modern shell, or manually run $0: the script under such a shell if you do have one." fi exit 1 fi fi fi SHELL=${CONFIG_SHELL-/bin/sh} export SHELL # Unset more variables known to interfere with behavior of common tools. CLICOLOR_FORCE= GREP_OPTIONS= unset CLICOLOR_FORCE GREP_OPTIONS ## --------------------- ## ## M4sh Shell Functions. ## ## --------------------- ## # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error "cannot create directory $as_dir" } # as_fn_mkdir_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith # as_fn_error ERROR [LINENO LOG_FD] # --------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with status $?, using 1 if that was 0. as_fn_error () { as_status=$?; test $as_status -eq 0 && as_status=1 if test "$3"; then as_lineno=${as_lineno-"$2"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $1" >&$3 fi $as_echo "$as_me: error: $1" >&2 as_fn_exit $as_status } # as_fn_error if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits as_lineno_1=$LINENO as_lineno_1a=$LINENO as_lineno_2=$LINENO as_lineno_2a=$LINENO eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -p'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -p' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -p' fi else as_ln_s='cp -p' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi if test -x / >/dev/null 2>&1; then as_test_x='test -x' else if ls -dL / >/dev/null 2>&1; then as_ls_L_option=L else as_ls_L_option= fi as_test_x=' eval sh -c '\'' if test -d "$1"; then test -d "$1/."; else case $1 in #( -*)set "./$1";; esac; case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( ???[sx]*):;;*)false;;esac;fi '\'' sh ' fi as_executable_p=$as_test_x # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME='qdbm-plus' PACKAGE_TARNAME='qdbm-plus' PACKAGE_VERSION='1.0.0' PACKAGE_STRING='qdbm-plus 1.0.0' PACKAGE_BUGREPORT='' PACKAGE_URL='' ac_subst_vars='LTLIBOBJS LIBOBJS AR LD MYOPTS MYDEFS TARGETS LIBREV LIBVER ac_ct_CXX CXXFLAGS CXX OBJEXT EXEEXT ac_ct_CC CPPFLAGS LDFLAGS CFLAGS CC target_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_URL PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL' ac_subst_files='' ac_user_opts=' enable_option_checking enable_debug enable_devel ' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS CXX CXXFLAGS CCC' # Initialize some variables set by options. ac_init_help= ac_init_version=false ac_unrecognized_opts= ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) as_fn_error "unrecognized option: \`$ac_option' Try \`$0 --help' for more information." ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) as_fn_error "invalid variable name: \`$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` as_fn_error "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) as_fn_error "unrecognized options: $ac_unrecognized_opts" ;; *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi # Check all directory arguments for consistency. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir do eval ac_val=\$$ac_var # Remove trailing slashes. case $ac_val in */ ) ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` eval $ac_var=\$ac_val;; esac # Be sure to have absolute directory names. case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac as_fn_error "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe $as_echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. If a cross compiler is detected then cross compile mode will be used." >&2 elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || as_fn_error "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || as_fn_error "pwd does not report name of working directory" # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." as_fn_error "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures qdbm-plus 1.0.0 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/qdbm-plus] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of qdbm-plus 1.0.0:";; esac cat <<\_ACEOF Optional Features: --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --enable-debug build for debugging --enable-devel build for development Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory CXX C++ compiler command CXXFLAGS C++ compiler flags Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to the package provider. _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for guested configure. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF qdbm-plus configure 1.0.0 generated by GNU Autoconf 2.65 Copyright (C) 2009 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi ## ------------------------ ## ## Autoconf initialization. ## ## ------------------------ ## # ac_fn_c_try_compile LINENO # -------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} as_fn_set_status $ac_retval } # ac_fn_c_try_compile # ac_fn_cxx_try_compile LINENO # ---------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_cxx_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} as_fn_set_status $ac_retval } # ac_fn_cxx_try_compile # ac_fn_c_try_link LINENO # ----------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} as_fn_set_status $ac_retval } # ac_fn_c_try_link cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by qdbm-plus $as_me 1.0.0, which was generated by GNU Autoconf 2.65. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. $as_echo "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) as_fn_append ac_configure_args1 " '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done { ac_configure_args0=; unset ac_configure_args0;} { ac_configure_args1=; unset ac_configure_args1;} # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo cat <<\_ASBOX ## ---------------- ## ## Cache variables. ## ## ---------------- ## _ASBOX echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo cat <<\_ASBOX ## ----------------- ## ## Output variables. ## ## ----------------- ## _ASBOX echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then cat <<\_ASBOX ## ------------------- ## ## File substitutions. ## ## ------------------- ## _ASBOX echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then cat <<\_ASBOX ## ----------- ## ## confdefs.h. ## ## ----------- ## _ASBOX echo cat confdefs.h echo fi test "$ac_signal" != 0 && $as_echo "$as_me: caught signal $ac_signal" $as_echo "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h $as_echo "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_URL "$PACKAGE_URL" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. ac_site_file1=NONE ac_site_file2=NONE if test -n "$CONFIG_SITE"; then ac_site_file1=$CONFIG_SITE elif test "x$prefix" != xNONE; then ac_site_file1=$prefix/share/config.site ac_site_file2=$prefix/etc/config.site else ac_site_file1=$ac_default_prefix/share/config.site ac_site_file2=$ac_default_prefix/etc/config.site fi for ac_site_file in "$ac_site_file1" "$ac_site_file2" do test "x$ac_site_file" = xNONE && continue if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 $as_echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 $as_echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 $as_echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then # differences in whitespace do not lead to failure. ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 $as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 $as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 $as_echo "$as_me: former value: \`$ac_old_val'" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 $as_echo "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 $as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} as_fn_error "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## ## -------------------- ## ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu # Export variables LIBVER=3 LIBREV=0 TARGETS="all" MYDEFS="" MYOPTS="" LD="ld" AR="ar" # Building paths pathtmp="$PATH" PATH="$HOME/bin:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin" PATH="$PATH:/usr/ccs/bin:/usr/ucb:/usr/xpg4/bin:/usr/xpg6/bin:$pathtmp" LIBRARY_PATH="$HOME/lib:/usr/local/lib:$LIBRARY_PATH" LD_LIBRARY_PATH="$HOME/lib:/usr/local/lib:$LD_LIBRARY_PATH" CPATH="$HOME/include:/usr/local/include:$CPATH" export PATH LIBRARY_PATH LD_LIBRARY_PATH CPATH #================================================================ # Options #================================================================ # Debug mode # Check whether --enable-debug was given. if test "${enable_debug+set}" = set; then : enableval=$enable_debug; fi if test "$enable_debug" = "yes" then TARGETS="debug" fi # Developping mode # Check whether --enable-devel was given. if test "${enable_devel+set}" = set; then : enableval=$enable_devel; fi if test "$enable_devel" = "yes" then TARGETS="devel" fi #================================================================ # Checking Commands to Build with #================================================================ # C compiler ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_CC+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_ac_ct_CC+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_CC+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_CC+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_CC+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_ac_ct_CC+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error "no acceptable C compiler found in \$PATH See \`config.log' for more details." "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 $as_echo_n "checking whether the C compiler works... " >&6; } ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # The possible output files: ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { { ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link_default") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an `-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else ac_file='' fi if test -z "$ac_file"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { as_fn_set_status 77 as_fn_error "C compiler cannot create executables See \`config.log' for more details." "$LINENO" 5; }; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 $as_echo_n "checking for C compiler default output file name... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 $as_echo "$ac_file" >&6; } ac_exeext=$ac_cv_exeext rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 $as_echo_n "checking for suffix of executables... " >&6; } if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error "cannot compute suffix of executables: cannot compile and link See \`config.log' for more details." "$LINENO" 5; } fi rm -f conftest conftest$ac_cv_exeext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 $as_echo "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { FILE *f = fopen ("conftest.out", "w"); return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF ac_clean_files="$ac_clean_files conftest.out" # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 $as_echo_n "checking whether we are cross compiling... " >&6; } if test "$cross_compiling" != yes; then { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if { ac_try='./conftest$ac_cv_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error "cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details." "$LINENO" 5; } fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 $as_echo "$cross_compiling" >&6; } rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 $as_echo_n "checking for suffix of object files... " >&6; } if test "${ac_cv_objext+set}" = set; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error "cannot compute suffix of object files: cannot compile See \`config.log' for more details." "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 $as_echo "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if test "${ac_cv_c_compiler_gnu+set}" = set; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if test "${ac_cv_prog_cc_g+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if test "${ac_cv_prog_cc_c89+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu # C++ compiler ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu if test -z "$CXX"; then if test -n "$CCC"; then CXX=$CCC else if test -n "$ac_tool_prefix"; then for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_CXX+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$CXX"; then ac_cv_prog_CXX="$CXX" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CXX=$ac_cv_prog_CXX if test -n "$CXX"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5 $as_echo "$CXX" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CXX" && break done fi if test -z "$CXX"; then ac_ct_CXX=$CXX for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CXX"; then ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_CXX="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CXX=$ac_cv_prog_ac_ct_CXX if test -n "$ac_ct_CXX"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5 $as_echo "$ac_ct_CXX" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CXX" && break done if test "x$ac_ct_CXX" = x; then CXX="g++" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CXX=$ac_ct_CXX fi fi fi fi # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C++ compiler" >&5 $as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; } if test "${ac_cv_cxx_compiler_gnu+set}" = set; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_cxx_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5 $as_echo "$ac_cv_cxx_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GXX=yes else GXX= fi ac_test_CXXFLAGS=${CXXFLAGS+set} ac_save_CXXFLAGS=$CXXFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5 $as_echo_n "checking whether $CXX accepts -g... " >&6; } if test "${ac_cv_prog_cxx_g+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_save_cxx_werror_flag=$ac_cxx_werror_flag ac_cxx_werror_flag=yes ac_cv_prog_cxx_g=no CXXFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : ac_cv_prog_cxx_g=yes else CXXFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : else ac_cxx_werror_flag=$ac_save_cxx_werror_flag CXXFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : ac_cv_prog_cxx_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cxx_werror_flag=$ac_save_cxx_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5 $as_echo "$ac_cv_prog_cxx_g" >&6; } if test "$ac_test_CXXFLAGS" = set; then CXXFLAGS=$ac_save_CXXFLAGS elif test $ac_cv_prog_cxx_g = yes; then if test "$GXX" = yes; then CXXFLAGS="-g -O2" else CXXFLAGS="-g" fi else if test "$GXX" = yes; then CXXFLAGS="-O2" else CXXFLAGS= fi fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test "$GXX" != "yes" then printf '#================================================================\n' 1>&2 printf '# WARNING: g++ (GCC) is required to build this package.\n' 1>&2 printf '#================================================================\n' 1>&2 fi if uname | egrep -i 'SunOS' > /dev/null 2>&1 then MYOPTS="-O1" fi if uname | egrep -i 'BSD' > /dev/null 2>&1 then MYOPTS="-O1" fi if gcc --version | egrep -i '^2\.(8|9)' > /dev/null 2>&1 then MYOPTS="-O1" fi # Linker printf 'checking for ld... ' if which ld | grep '/ld$' > /dev/null 2>&1 then LD=`which ld` printf '%s\n' "$LD" else printf 'no\n' printf '#================================================================\n' 1>&2 printf '# WARNING: ld is not found in PATH.\n' 1>&2 printf '#================================================================\n' 1>&2 fi # Archiver printf 'checking for ar... ' if which ar | grep '/ar$' > /dev/null 2>&1 then AR=`which ar` printf '%s\n' "$AR" else printf 'no\n' printf '#================================================================\n' 1>&2 printf '# WARNING: ar is not found in PATH.\n' 1>&2 printf '#================================================================\n' 1>&2 fi #================================================================ # Checking Libraries #================================================================ # Underlying libraries { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lc" >&5 $as_echo_n "checking for main in -lc... " >&6; } if test "${ac_cv_lib_c_main+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lc $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_c_main=yes else ac_cv_lib_c_main=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_c_main" >&5 $as_echo "$ac_cv_lib_c_main" >&6; } if test "x$ac_cv_lib_c_main" = x""yes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBC 1 _ACEOF LIBS="-lc $LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lrt" >&5 $as_echo_n "checking for main in -lrt... " >&6; } if test "${ac_cv_lib_rt_main+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lrt $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_rt_main=yes else ac_cv_lib_rt_main=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rt_main" >&5 $as_echo "$ac_cv_lib_rt_main" >&6; } if test "x$ac_cv_lib_rt_main" = x""yes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBRT 1 _ACEOF LIBS="-lrt $LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lpthread" >&5 $as_echo_n "checking for main in -lpthread... " >&6; } if test "${ac_cv_lib_pthread_main+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lpthread $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_pthread_main=yes else ac_cv_lib_pthread_main=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_main" >&5 $as_echo "$ac_cv_lib_pthread_main" >&6; } if test "x$ac_cv_lib_pthread_main" = x""yes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBPTHREAD 1 _ACEOF LIBS="-lpthread $LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lz" >&5 $as_echo_n "checking for main in -lz... " >&6; } if test "${ac_cv_lib_z_main+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lz $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_z_main=yes else ac_cv_lib_z_main=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_z_main" >&5 $as_echo "$ac_cv_lib_z_main" >&6; } if test "x$ac_cv_lib_z_main" = x""yes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBZ 1 _ACEOF LIBS="-lz $LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -llzo2" >&5 $as_echo_n "checking for main in -llzo2... " >&6; } if test "${ac_cv_lib_lzo2_main+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-llzo2 $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_lzo2_main=yes else ac_cv_lib_lzo2_main=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_lzo2_main" >&5 $as_echo "$ac_cv_lib_lzo2_main" >&6; } if test "x$ac_cv_lib_lzo2_main" = x""yes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBLZO2 1 _ACEOF LIBS="-llzo2 $LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lbz2" >&5 $as_echo_n "checking for main in -lbz2... " >&6; } if test "${ac_cv_lib_bz2_main+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lbz2 $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_bz2_main=yes else ac_cv_lib_bz2_main=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_bz2_main" >&5 $as_echo "$ac_cv_lib_bz2_main" >&6; } if test "x$ac_cv_lib_bz2_main" = x""yes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBBZ2 1 _ACEOF LIBS="-lbz2 $LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -liconv" >&5 $as_echo_n "checking for main in -liconv... " >&6; } if test "${ac_cv_lib_iconv_main+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-liconv $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_iconv_main=yes else ac_cv_lib_iconv_main=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_iconv_main" >&5 $as_echo "$ac_cv_lib_iconv_main" >&6; } if test "x$ac_cv_lib_iconv_main" = x""yes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBICONV 1 _ACEOF LIBS="-liconv $LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lstdc++" >&5 $as_echo_n "checking for main in -lstdc++... " >&6; } if test "${ac_cv_lib_stdcpp_main+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lstdc++ $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_stdcpp_main=yes else ac_cv_lib_stdcpp_main=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_stdcpp_main" >&5 $as_echo "$ac_cv_lib_stdcpp_main" >&6; } if test "x$ac_cv_lib_stdcpp_main" = x""yes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBSTDC__ 1 _ACEOF LIBS="-lstdc++ $LIBS" fi # Fundamental QDBM libraries { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lqdbm" >&5 $as_echo_n "checking for main in -lqdbm... " >&6; } if test "${ac_cv_lib_qdbm_main+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lqdbm $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_qdbm_main=yes else ac_cv_lib_qdbm_main=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_qdbm_main" >&5 $as_echo "$ac_cv_lib_qdbm_main" >&6; } if test "x$ac_cv_lib_qdbm_main" = x""yes; then : true else printf 'checking whether /usr/local/lib/libqdbm.* is... ' if ls /usr/local/lib/libqdbm.* > /dev/null 2>&1 then printf 'yes\n' else printf 'no\n' printf '#================================================================\n' 1>&2 printf '# WARNING: Install QDBM libraries before installation.\n' 1>&2 printf '#================================================================\n' 1>&2 fi fi # For old BSDs if uname -a | grep BSD > /dev/null && test -f /usr/lib/libc_r.a && test ! -f /usr/lib/libpthread.a then LIBS=`printf '%s' "$LIBS" | sed 's/-lc/-lc_r/g'` fi # Duplication of QDBM for C++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lxqdbm" >&5 $as_echo_n "checking for main in -lxqdbm... " >&6; } if test "${ac_cv_lib_xqdbm_main+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lxqdbm $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_xqdbm_main=yes else ac_cv_lib_xqdbm_main=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_xqdbm_main" >&5 $as_echo "$ac_cv_lib_xqdbm_main" >&6; } if test "x$ac_cv_lib_xqdbm_main" = x""yes; then : printf '#================================================================\n' 1>&2 printf '# WARNING: The existing library was detected.\n' 1>&2 printf '#================================================================\n' 1>&2 fi #================================================================ # Generic Settings #================================================================ # Export variables # Targets ac_config_files="$ac_config_files Makefile" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then test "x$cache_file" != "x/dev/null" && { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} cat confcache >$cache_file else { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' # Transform confdefs.h into DEFS. # Protect against shell expansion while executing Makefile rules. # Protect against Makefile macro expansion. # # If the first sed substitution is executed (which looks for macros that # take arguments), then branch to the quote section. Otherwise, # look for a macro that doesn't take arguments. ac_script=' :mline /\\$/{ N s,\\\n,, b mline } t clear :clear s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g t quote s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g t quote b any :quote s/[ `~#$^&*(){}\\|;'\''"<>?]/\\&/g s/\[/\\&/g s/\]/\\&/g s/\$/$$/g H :any ${ g s/^\n// s/\n/ /g p } ' DEFS=`sed -n "$ac_script" confdefs.h` ac_libobjs= ac_ltlibobjs= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`$as_echo "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs : ${CONFIG_STATUS=./config.status} ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 $as_echo "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # as_fn_error ERROR [LINENO LOG_FD] # --------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with status $?, using 1 if that was 0. as_fn_error () { as_status=$?; test $as_status -eq 0 && as_status=1 if test "$3"; then as_lineno=${as_lineno-"$2"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $1" >&$3 fi $as_echo "$as_me: error: $1" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -p'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -p' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -p' fi else as_ln_s='cp -p' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi if test -x / >/dev/null 2>&1; then as_test_x='test -x' else if ls -dL / >/dev/null 2>&1; then as_ls_L_option=L else as_ls_L_option= fi as_test_x=' eval sh -c '\'' if test -d "$1"; then test -d "$1/."; else case $1 in #( -*)set "./$1";; esac; case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( ???[sx]*):;;*)false;;esac;fi '\'' sh ' fi as_executable_p=$as_test_x # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 ## ----------------------------------- ## ## Main body of $CONFIG_STATUS script. ## ## ----------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by qdbm-plus $as_me 1.0.0, which was generated by GNU Autoconf 2.65. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ \`$as_me' instantiates files and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit --config print configuration, then exit -q, --quiet, --silent do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE Configuration files: $config_files Report bugs to the package provider." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ qdbm-plus config.status 1.0.0 configured by $0, generated by GNU Autoconf 2.65, with options \\"\$ac_cs_config\\" Copyright (C) 2009 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) $as_echo "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) $as_echo "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --he | --h | --help | --hel | -h ) $as_echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) as_fn_error "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX $as_echo "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; *) as_fn_error "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= trap 'exit_status=$? { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error "cannot create a temporary directory in ." "$LINENO" 5 # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with `./config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=`echo X | tr X '\015'` # On cygwin, bash can eat \r inside `` if the user requested igncr. # But we know of no other shell where ac_cr would be empty at this # point, so we can use a bashism as a fallback. if test "x$ac_cr" = x; then eval ac_cr=\$\'\\r\' fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_num=`echo "$ac_subst_vars" | grep -c '$'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>"\$tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\)..*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\)..*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' >$CONFIG_STATUS || ac_write_fail=1 rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$tmp/subs1.awk" > "$tmp/subs.awk" \ || as_fn_error "could not setup config files machinery" "$LINENO" 5 _ACEOF # VPATH may cause trouble with some makes, so we remove $(srcdir), # ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=/{ s/:*\$(srcdir):*/:/ s/:*\${srcdir}:*/:/ s/:*@srcdir@:*/:/ s/^\([^=]*=[ ]*\):*/\1/ s/:*$// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" eval set X " :F $CONFIG_FILES " shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) as_fn_error "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || as_fn_error "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 $as_echo "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`$as_echo "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$tmp/stdin" \ || as_fn_error "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 $as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$tmp/subs.awk" >$tmp/out \ || as_fn_error "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } && { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined." >&5 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined." >&2;} rm -f "$tmp/stdin" case $ac_file in -) cat "$tmp/out" && rm -f "$tmp/out";; *) rm -f "$ac_file" && mv "$tmp/out" "$ac_file";; esac \ || as_fn_error "could not create $ac_file" "$LINENO" 5 ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || as_fn_error "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit $? fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi # END OF FILE qdbm-1.8.78/plus/xvilla.h0000644000175000017500000007031610505721701014204 0ustar mikiomikio/************************************************************************************************* * C++ API of Villa, the advanced API of QDBM * Copyright (C) 2000-2006 Mikio Hirabayashi * This file is part of QDBM, Quick Database Manager. * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU * Lesser General Public License as published by the Free Software Foundation; either version * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * You should have received a copy of the GNU Lesser General Public License along with QDBM; if * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. *************************************************************************************************/ #ifndef _XVILLA_H /* duplication check */ #define _XVILLA_H #include #include extern "C" { #include #include #include #include #include } /** * Error container for Villa. */ class qdbm::Villa_error : public virtual DBM_error { //---------------------------------------------------------------- // public member functions //---------------------------------------------------------------- public: /** * Create an instance. */ Villa_error() throw(); /** * Create an instance. * @param ecode the error code. */ Villa_error(int ecode) throw(); /** * Copy constructor. * @param ve a source instance. */ Villa_error(const Villa_error& ve) throw(); /** * Release resources of the instance. */ virtual ~Villa_error() throw(); /** * Assignment operator. * @param ve a source instance. * @return reference to itself. */ Villa_error& operator =(const Villa_error& ve) throw(); /** * Assignment operator. * @param ecode the error code. * @return reference to itself. */ Villa_error& operator =(int ecode) throw(); /** * Equality operator. * @param ve a comparing instance. * @return true if both equal, else, false. */ virtual bool operator ==(const Villa_error& ve) const throw(); /** * Inequality operator. * @param ve a comparing instance. * @return true if both do not equal, else, false. */ virtual bool operator !=(const Villa_error& ve) const throw(); /** * Equality operator. * @param ecode a comparing error code. * @return true if both equal, else, false. */ virtual bool operator ==(int ecode) const throw(); /** * Inequality operator. * @param ecode a comparing error code. * @return true if both do not equal, else, false. */ virtual bool operator !=(int ecode) const throw(); /** * Cast operator into pointer to char. * @return the pointer to the string. */ virtual operator const char*() const throw(); /** * Get the error code. * @return the error code. */ virtual int code() const throw(); /** * Get the error message. * @return the pointer to the string. */ virtual const char* message() const throw(); //---------------------------------------------------------------- // private member variables //---------------------------------------------------------------- private: /** The error code. */ int ecode; }; /** * C++ API of Villa, the basic API of QDBM. */ class qdbm::Villa : public virtual ADBM { //---------------------------------------------------------------- // public static member constants //---------------------------------------------------------------- public: static const int ENOERR; ///< error code: no error static const int EFATAL; ///< error code: with fatal error static const int EMODE; ///< error code: invalid mode static const int EBROKEN; ///< error code: broken database file static const int EKEEP; ///< error code: existing record static const int ENOITEM; ///< error code: no item found static const int EALLOC; ///< error code: memory allocation error static const int EMAP; ///< error code: memory mapping error static const int EOPEN; ///< error code: open error static const int ECLOSE; ///< error code: close error static const int ETRUNC; ///< error code: trunc error static const int ESYNC; ///< error code: sync error static const int ESTAT; ///< error code: stat error static const int ESEEK; ///< error code: seek error static const int EREAD; ///< error code: read error static const int EWRITE; ///< error code: write error static const int ELOCK; ///< error code: lock error static const int EUNLINK; ///< error code: unlink error static const int EMKDIR; ///< error code: mkdir error static const int ERMDIR; ///< error code: rmdir error static const int EMISC; ///< error code: miscellaneous error static const int OREADER; ///< open mode: open as a reader static const int OWRITER; ///< open mode: open as a writer static const int OCREAT; ///< open mode: writer creating static const int OTRUNC; ///< open mode: writer truncating static const int ONOLCK; ///< open mode: open without locking static const int OLCKNB; ///< open mode: lock without blocking static const int OZCOMP; ///< open mode: compress leaves with ZLIB static const int OYCOMP; ///< open mode: compress leaves with LZO static const int OXCOMP; ///< open mode: compress leaves with BZIP2 static const int DOVER; ///< write mode: overwrite the existing value static const int DKEEP; ///< write mode: keep the existing value static const int DCAT; ///< write mode: concatenate values static const int DDUP; ///< write mode: allow duplication of keys static const int DDUPR; ///< write mode: allow duplication with reverse order static const int JFORWARD; ///< jump mode: step forward static const int JBACKWARD; ///< jump mode: step backward static const int CPCURRENT; ///< insertion mode: overwrite the current record static const int CPBEFORE; ///< insertion mode: insert before the current record static const int CPAFTER; ///< insertion mode: insert after the current record //---------------------------------------------------------------- // public static member functions //---------------------------------------------------------------- public: /** * Get the version information. * @return the string of the version information. */ static const char* version() throw(); /** * Remove a database directory. * @param name the name of a database directory. * @throw Villa_error if an error occurs. */ static void remove(const char* name) throw(Villa_error); /** * Compare keys of two records by lexical order. * @param aptr the pointer to the region of one key. * @param asiz the size of the region of one key. * @param bptr the pointer to the region of the other key. * @param bsiz the size of the region of the other key. * @return positive if the former is big, negative if the latter is big, 0 if both are * equivalent. */ static int cmplex(const char *aptr, int asiz, const char *bptr, int bsiz) throw(); /** * Compare keys of two records as integers. * @param aptr the pointer to the region of one key. * @param asiz the size of the region of one key. * @param bptr the pointer to the region of the other key. * @param bsiz the size of the region of the other key. * @return positive if the former is big, negative if the latter is big, 0 if both are * equivalent. */ static int cmpint(const char *aptr, int asiz, const char *bptr, int bsiz) throw(); /** * Compare keys of two records as numbers of big endian. * @param aptr the pointer to the region of one key. * @param asiz the size of the region of one key. * @param bptr the pointer to the region of the other key. * @param bsiz the size of the region of the other key. * @return positive if the former is big, negative if the latter is big, 0 if both are * equivalent. */ static int cmpnum(const char *aptr, int asiz, const char *bptr, int bsiz) throw(); /** * Compare keys of two records as decimal strings. * @param aptr the pointer to the region of one key. * @param asiz the size of the region of one key. * @param bptr the pointer to the region of the other key. * @param bsiz the size of the region of the other key. * @return positive if the former is big, negative if the latter is big, 0 if both are * equivalent. */ static int cmpdec(const char *aptr, int asiz, const char *bptr, int bsiz) throw(); //---------------------------------------------------------------- // public member functions //---------------------------------------------------------------- public: /** * Get the database handle. * @param name the name of a database file. * @param omode the connection mode: `Villa::OWRITER' as a writer, `Villa::OREADER' as * a reader. If the mode is `Villa::OWRITER', the following may be added by bitwise or: * `Villa::OCREAT', which means it creates a new database if not exist, `Villa::OTRUNC', * which means it creates a new database regardless if one exists, `Villa::OZCOMP', which means * leaves in the database are compressed with ZLIB, `Villa::OYCOMP', which means leaves in the * database are compressed with LZO, `Villa::OXCOMP', which means leaves in the database are * compressed with BZIP2. Both of `Villa::OREADER' and `Villa::OWRITER' can be added to by * bitwise or: `Villa::ONOLCK', which means it opens a database file without file locking, or * `Villa::OLCKNB', which means locking is performed without blocking. * @param cmp the comparing function: `Villa::cmplex' comparing keys in lexical order, * `Villa::cmpint' comparing keys as objects of `int' in native byte order, `Villa::cmpnum' * comparing keys as numbers of big endian, `Villa::cmpdec' comparing keys as decimal strings. * Any function compatible with them can be assigned to the comparing function. The comparing * function should be kept same in the life of a database. * @throw Villa_error if an error occurs. * @note While connecting as a writer, an exclusive lock is invoked to the database file. * While connecting as a reader, a shared lock is invoked to the database file. The thread * blocks until the lock is achieved. `Villa::OZCOMP', `Villa::OYCOMP', and `Villa::OXCOMP' * are available only if QDBM was built each with ZLIB, LZO, and BZIP2 enabled. If * `Villa::ONOLCK' is used, the application is responsible for exclusion control. */ Villa(const char* name, int omode = Villa::OREADER, VLCFUNC cmp = Villa::cmplex) throw(Villa_error); /** * Release the resources. * @note If the database handle is not closed yet, it is closed. */ virtual ~Villa() throw(); /** * Close the database handle. * @throw Villa_error if an error occurs. * @note Updating a database is assured to be written when the handle is closed. If a writer * opens a database but does not close it appropriately, the database will be broken. If the * transaction is activated and not committed, it is aborted. */ virtual void close() throw(Villa_error); /** * Store a record. * @param kbuf the pointer to the region of a key. * @param ksiz the size of the region of the key. If it is negative, the size is assigned * with `std::strlen(kbuf)'. * @param vbuf the pointer to the region of a value. * @param vsiz the size of the region of the value. If it is negative, the size is assigned * with `std::strlen(vbuf)'. * @param dmode behavior when the key overlaps, by the following values: `Villa::DOVER', * which means the specified value overwrites the existing one, `Villa::DKEEP', which means * the existing value is kept, `Villa::DCAT', which means the specified value is concatenated * at the end of the existing value, `Villa::DDUP', which means duplication of keys is allowed * and the specified value is added as the last one, `Villa::DDUPR', which means duplication of * keys is allowed and the specified value is added as the first one. * @return always true. However, if the silent flag is true and replace is cancelled, false is * returned instead of exception. * @throw Villa_error if an error occurs or replace is cancelled. * @note The cursor becomes unavailable due to updating database. */ virtual bool put(const char* kbuf, int ksiz, const char* vbuf, int vsiz, int dmode = Villa::DOVER) throw(Villa_error); /** * Delete a record. * @param kbuf the pointer to the region of a key. * @param ksiz the size of the region of the key. If it is negative, the size is assigned * with `std::strlen(kbuf)'. * @return always true. However, if the silent flag is true and no record corresponds, false * is returned instead of exception. * @throw Villa_error if an error occurs or no record corresponds. * @note When the key of duplicated records is specified, the first record of the same key * is deleted. The cursor becomes unavailable due to updating database. */ virtual bool out(const char* kbuf, int ksiz) throw(Villa_error); /** * Retrieve a record. * @param kbuf the pointer to the region of a key. * @param ksiz the size of the region of the key. If it is negative, the size is assigned * with `std::strlen(kbuf)'. * @param sp the pointer to a variable to which the size of the region of the return value * is assigned. If it is 0, it is not used. * @return the pointer to the region of the value of the corresponding record. If the silent * flag is true and no record corresponds, 0 is returned instead of exception. * @throw Villa_error if an error occurs or no record corresponds. * @note When the key of duplicated records is specified, the value of the first record of * the same key is selected. Because an additional zero code is appended at the end of the * region of the return value, the return value can be treated as a character string. * Because the region of the return value is allocated with the `std::malloc' call, it * should be released with the `std::free' call if it is no longer in use. */ virtual char* get(const char* kbuf, int ksiz, int* sp = 0) throw(Villa_error); /** * Get the size of the value of a record. * @param kbuf the pointer to the region of a key. * @param ksiz the size of the region of the key. If it is negative, the size is assigned * with `std::strlen(kbuf)'. * @return the size of the value of the corresponding record. If the silent flag is true and * no record corresponds, -1 is returned instead of exception. If multiple records correspond, * the size of the first is returned. * @throw Villa_error if an error occurs or no record corresponds. */ virtual int vsiz(const char* kbuf, int ksiz) throw(Villa_error); /** * Get the number of records corresponding a key. * @param kbuf the pointer to the region of a key. * @param ksiz the size of the region of the key. If it is negative, the size is assigned * with `std::strlen(kbuf)'. * @return the number of corresponding records. If no record corresponds, 0 is returned. * @throw Villa_error if an error occurs. */ virtual int vnum(const char* kbuf, int ksiz) throw(Villa_error); /** * Move the cursor to the first record. * @return always true. However, if the silent flag is true and no record corresponds, false * is returned instead of exception. * @throw Villa_error if an error occurs or there is no record in the database. */ virtual bool curfirst() throw(Villa_error); /** * Move the cursor to the last record. * @return always true. However, if the silent flag is true and no record corresponds, false * is returned instead of exception. * @throw Villa_error if an error occurs or there is no record in the database. */ virtual bool curlast() throw(Villa_error); /** * Move the cursor to the previous record. * @return always true. However, if the silent flag is true and no record corresponds, false * is returned instead of exception. * @throw Villa_error if an error occurs or there is no previous record. */ virtual bool curprev() throw(Villa_error); /** * Move the cursor to the next record. * @return always true. However, if the silent flag is true and no record corresponds, false * is returned instead of exception. * @throw Villa_error if an error occurs or there is no next record. */ virtual bool curnext() throw(Villa_error); /** * Move the cursor to a position around a record. * @param kbuf the pointer to the region of a key. * @param ksiz the size of the region of the key. If it is negative, the size is assigned * with `std::strlen(kbuf)'. * @param jmode detail adjustment: `Villa::JFORWARD', which means that the cursor is set to * the first record of the same key and that the cursor is set to the next substitute if * completely matching record does not exist, `Villa::JBACKWARD', which means that the cursor * is set to the last record of the same key and that the cursor is set to the previous * substitute if completely matching record does not exist. * @return always true. However, if the silent flag is true and no record corresponds, false * is returned instead of exception. * @throw Villa_error if an error occurs or there is no record corresponding the condition. */ virtual bool curjump(const char* kbuf, int ksiz, int jmode = Villa::JFORWARD) throw(Villa_error); /** * Get the key of the record where the cursor is. * @param sp the pointer to a variable to which the size of the region of the return value * is assigned. If it is 0, it is not used. * @return the pointer to the region of the key of the corresponding record. If the silent * flag is true and no record corresponds, 0 is returned instead of exception. * @throw Villa_error if an error occurs or no record corresponds to the cursor. * @note Because an additional zero code is appended at the end of the region of the return * value, the return value can be treated as a character string. Because the region of the * return value is allocated with the `std::malloc' call, it should be released with the * `std::free' call if it is no longer in use. */ virtual char* curkey(int* sp = 0) throw(Villa_error); /** * Get the value of the record where the cursor is. * @param sp the pointer to a variable to which the size of the region of the return value * is assigned. If it is 0, it is not used. * @return the pointer to the region of the value of the corresponding record. If the silent * flag is true and no record corresponds, 0 is returned instead of exception. * @throw Villa_error if an error occurs or no record corresponds to the cursor. * @note Because an additional zero code is appended at the end of the region of the return * value, the return value can be treated as a character string. Because the region of the * return value is allocated with the `std::malloc' call, it should be released with the * `std::free' call if it is no longer in use. */ virtual char* curval(int* sp = 0) throw(Villa_error); /** * Insert a record around the cursor. * @param vbuf the pointer to the region of a value. * @param vsiz the size of the region of the value. If it is negative, the size is assigned * with `std::strlen(vbuf)'. * @param cpmode detail adjustment: `Villa::CPCURRENT', which means that the value of the * current record is overwritten, `Villa::CPBEFORE', which means that a new record is inserted * before the current record, `Villa::CPAFTER', which means that a new record is inserted after * the current record. * @return always true. However, if the silent flag is true and no record corresponds to the * cursor, false is returned instead of exception. * @throw Villa_error if an error occurs or no record corresponds to the cursor. * @note After insertion, the cursor is moved to the inserted record. */ virtual bool curput(const char* vbuf, int vsiz, int cpmode = Villa::CPCURRENT) throw(Villa_error); /** * Delete the record where the cursor is. * @return always true. However, if the silent flag is true and no record corresponds to the * cursor, false is returned instead of exception. * @throw Villa_error if an error occurs or no record corresponds to the cursor. * @note After deletion, the cursor is moved to the next record if possible. */ virtual bool curout() throw(Villa_error); /** * Set the tuning parameters for performance. * @param lrecmax the max number of records in a leaf node of B+ tree. If it is not more * than 0, the default value is specified. * @param nidxmax the max number of indexes in a non-leaf node of B+ tree. If it is not more * than 0, the default value is specified. * @param lcnum the max number of caching leaf nodes. If it is not more than 0, the default * value is specified. * @param ncnum the max number of caching non-leaf nodes. If it is not more than 0, the * default value is specified. * @throw Villa_error if an error occurs. * @note The default setting is equivalent to `settuning(49, 192, 1024, 512)'. Because tuning * paremeters are not saved in a database, you should specify them every opening a database. */ virtual void settuning(int lrecmax, int nidxmax, int lcnum, int ncnum) throw(Villa_error); /** * Synchronize updating contents with the file and the device. * @throw Villa_error if an error occurs. * @note This function is useful when another process uses the connected database file. This * function shuold not be used while the transaction is activated. */ virtual void sync() throw(Villa_error); /** * Optimize a database. * @throw Villa_error if an error occurs. * @note In an alternating succession of deleting and storing with overwrite or concatenate, * dispensable regions accumulate. This function is useful to do away with them. This * function shuold not be used while the transaction is activated. */ virtual void optimize() throw(Villa_error); /** * Get the name of the database. * @return the pointer to the region of the name of the database. * @throw Villa_error if an error occurs. * @note Because the region of the return value is allocated with the `std::malloc' call, * it should be released with the `std::free' call if it is no longer in use. */ virtual char* name() throw(Villa_error); /** * Get the size of the database file. * @return the size of the database file. * @throw Villa_error if an error occurs. * @note Because of the I/O buffer, the return value may be less than the real size. */ virtual int fsiz() throw(Villa_error); /** * Get the number of the leaf nodes of B+ tree. * @return the number of the leaf nodes. * @throw Villa_error if an error occurs. */ virtual int lnum() throw(Villa_error); /** * Get the number of the non-leaf nodes of B+ tree. * @return the number of the non-leaf nodes. * @throw Villa_error if an error occurs. */ virtual int nnum() throw(Villa_error); /** * Get the number of the records stored in a database. * @return the number of the records stored in the database. * @throw Villa_error if an error occurs. */ virtual int rnum() throw(Villa_error); /** * Check whether the database handle is a writer or not. * @return true if the handle is a writer, false if not. * @throw Villa_error if an error occurs. */ virtual bool writable() throw(Villa_error); /** * Check whether the database has a fatal error or not. * @return true if the database has a fatal error, false if not. * @throw Villa_error if an error occurs. */ virtual bool fatalerror() throw(Villa_error); /** * Get the inode number of the database file. * @return the inode number of the database file. * @throw Villa_error if an error occurs. */ virtual int inode() throw(Villa_error); /** * Get the last modified time of the database. * @return the last modified time the database. * @throw Villa_error if an error occurs. */ virtual time_t mtime() throw(Villa_error); /** * Begin the transaction. * @throw Villa_error if an error occurs. * @note If a thread is already in the transaction, the other threads block until the prius * is out of the transaction. Only one transaction can be activated with a database handle * at the same time. */ virtual void tranbegin() throw(Villa_error); /** * Commit the transaction. * @throw Villa_error if an error occurs. * @note Updating a database in the transaction is fixed when it is committed successfully. * Any other thread except for the one which began the transaction should not call this * function. */ virtual void trancommit() throw(Villa_error); /** * Abort the transaction. * @throw Villa_error if an error occurs. * @note Updating a database in the transaction is discarded when it is aborted. The state * of the database is rollbacked to before transaction. Any other thread except for the one * which began the transaction should not call this function. */ virtual void tranabort() throw(Villa_error); /** * Store a record. * @param key reference to a key object. * @param val reference to a value object. * @param replace whether the existing value is to be overwritten or not. * @throw Villa_error if an error occurs or replace is cancelled. */ virtual void storerec(const Datum& key, const Datum& val, bool replace = true) throw(Villa_error); /** * Delete a record. * @param key reference to a key object. * @throw Villa_error if an error occurs or no record corresponds. */ virtual void deleterec(const Datum& key) throw(Villa_error); /** * Fetch a record. * @param key reference to a key object. * @return a temporary instance of the value of the corresponding record. * @throw Villa_error if an error occurs or no record corresponds. */ virtual Datum fetchrec(const Datum& key) throw(Villa_error); /** * Get the first key. * @return a temporary instance of the key of the first record. * @throw Villa_error if an error occurs or no record corresponds. */ virtual Datum firstkey() throw(Villa_error); /** * Get the next key. * @return a temporary instance of the key of the next record. * @throw Villa_error if an error occurs or no record corresponds. */ virtual Datum nextkey() throw(Villa_error); /** * Check whether a fatal error occured or not. * @return true if the database has a fatal error, false if not. * @throw Villa_error if an error occurs. */ virtual bool error() throw(Villa_error); //---------------------------------------------------------------- // public member variables //---------------------------------------------------------------- public: bool silent; ///< whether to repress frequent exceptions //---------------------------------------------------------------- // private member variables //---------------------------------------------------------------- private: VILLA* villa; ///< internal database handle pthread_mutex_t mymutex; ///< internal mutex pthread_mutex_t tranmutex; ///< mutex for the transaction //---------------------------------------------------------------- // private member functions //---------------------------------------------------------------- private: /** copy constructor: This should not be used. */ Villa(const Villa& villa) throw(Villa_error); /** assignment operator: This should not be used. */ Villa& operator =(const Villa& villa) throw(Villa_error); /** lock the database. */ bool lock(); /** unlock the database. */ void unlock(); }; #endif /* duplication check */ /* END OF FILE */ qdbm-1.8.78/hvmgr.c0000644000175000017500000003246110610627747013053 0ustar mikiomikio/************************************************************************************************* * Utility for debugging Hovel and its applications * Copyright (C) 2000-2007 Mikio Hirabayashi * This file is part of QDBM, Quick Database Manager. * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU * Lesser General Public License as published by the Free Software Foundation; either version * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * You should have received a copy of the GNU Lesser General Public License along with QDBM; if * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. *************************************************************************************************/ #include #include #include #include #include #include #include #undef TRUE #define TRUE 1 /* boolean true */ #undef FALSE #define FALSE 0 /* boolean false */ #define ALIGNSIZ 16 /* basic size of alignment */ /* for RISC OS */ #if defined(__riscos__) || defined(__riscos) #include int __riscosify_control = __RISCOSIFY_NO_PROCESS; #endif /* global variables */ const char *progname; /* program name */ /* function prototypes */ int main(int argc, char **argv); void usage(void); char *hextoobj(const char *str, int *sp); int runcreate(int argc, char **argv); int runstore(int argc, char **argv); int rundelete(int argc, char **argv); int runfetch(int argc, char **argv); int runlist(int argc, char **argv); int runoptimize(int argc, char **argv); void pgerror(const char *name); void printobj(const char *obj, int size); void printobjhex(const char *obj, int size); int docreate(char *name, int qdbm, int bnum, int dnum, int sparse); int dostore(char *name, int qdbm, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int ins); int dodelete(char *name, int qdbm, const char *kbuf, int ksiz); int dofetch(char *name, int qdbm, const char *kbuf, int ksiz, int ox, int nb); int dolist(char *name, int qdbm, int ox); int dooptimize(char *name, int qdbm); /* main routine */ int main(int argc, char **argv){ int rv; cbstdiobin(); progname = argv[0]; if(argc < 2) usage(); rv = 0; if(!strcmp(argv[1], "create")){ rv = runcreate(argc, argv); } else if(!strcmp(argv[1], "store")){ rv = runstore(argc, argv); } else if(!strcmp(argv[1], "delete")){ rv = rundelete(argc, argv); } else if(!strcmp(argv[1], "fetch")){ rv = runfetch(argc, argv); } else if(!strcmp(argv[1], "list")){ rv = runlist(argc, argv); } else if(!strcmp(argv[1], "optimize")){ rv = runoptimize(argc, argv); } else { usage(); } return rv; } /* print the usage and exit */ void usage(void){ fprintf(stderr, "%s: administration utility for Hovel\n", progname); fprintf(stderr, "\n"); fprintf(stderr, "usage:\n"); fprintf(stderr, " %s create [-qdbm bnum dnum] [-s] name\n", progname); fprintf(stderr, " %s store [-qdbm] [-kx] [-vx|-vf] [-insert] name key val\n", progname); fprintf(stderr, " %s delete [-qdbm] [-kx] name key\n", progname); fprintf(stderr, " %s fetch [-qdbm] [-kx] [-ox] [-n] name key\n", progname); fprintf(stderr, " %s list [-qdbm] [-ox] name\n", progname); fprintf(stderr, " %s optimize [-qdbm] name\n", progname); fprintf(stderr, "\n"); exit(1); } /* create a binary object from a hexadecimal string */ char *hextoobj(const char *str, int *sp){ char *buf, mbuf[3]; int len, i, j; len = strlen(str); if(!(buf = malloc(len + 1))) return NULL; j = 0; for(i = 0; i < len; i += 2){ while(strchr(" \n\r\t\f\v", str[i])){ i++; } if((mbuf[0] = str[i]) == '\0') break; if((mbuf[1] = str[i+1]) == '\0') break; mbuf[2] = '\0'; buf[j++] = (char)strtol(mbuf, NULL, 16); } buf[j] = '\0'; *sp = j; return buf; } /* parse arguments of create command */ int runcreate(int argc, char **argv){ char *name; int i, sb, qdbm, bnum, dnum, rv; name = NULL; sb = FALSE; qdbm = FALSE; bnum = -1; dnum = -1; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ if(!strcmp(argv[i], "-qdbm")){ qdbm = TRUE; if(++i >= argc) usage(); bnum = atoi(argv[i]); if(++i >= argc) usage(); dnum = atoi(argv[i]); } else if(!strcmp(argv[i], "-s")){ sb = TRUE; } else { usage(); } } else if(!name){ name = argv[i]; } else { usage(); } } if(!name) usage(); rv = docreate(name, qdbm, bnum, dnum, sb); return rv; } /* parse arguments of store command */ int runstore(int argc, char **argv){ char *name, *key, *val, *kbuf, *vbuf; int i, qdbm, kx, vx, vf, ins, ksiz, vsiz, rv; name = NULL; qdbm = FALSE; kx = FALSE; vx = FALSE; vf = FALSE; ins = FALSE; key = NULL; val = NULL; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ if(!strcmp(argv[i], "-qdbm")){ qdbm = TRUE; } else if(!strcmp(argv[i], "-kx")){ kx = TRUE; } else if(!strcmp(argv[i], "-vx")){ vx = TRUE; } else if(!strcmp(argv[i], "-vf")){ vf = TRUE; } else if(!strcmp(argv[i], "-insert")){ ins = TRUE; } else { usage(); } } else if(!name){ name = argv[i]; } else if(!key){ key = argv[i]; } else if(!val){ val = argv[i]; } else { usage(); } } if(!name || !key || !val) usage(); if(kx){ kbuf = hextoobj(key, &ksiz); } else { kbuf = cbmemdup(key, -1); ksiz = strlen(kbuf); } if(vx){ vbuf = hextoobj(val, &vsiz); } else if(vf){ vbuf = cbreadfile(val, &vsiz); } else { vbuf = cbmemdup(val, -1); vsiz = strlen(vbuf); } if(kbuf && vbuf){ rv = dostore(name, qdbm, kbuf, ksiz, vbuf, vsiz, ins); } else { if(vf){ fprintf(stderr, "%s: %s: cannot read\n", progname, val); } else { fprintf(stderr, "%s: out of memory\n", progname); } rv = 1; } free(kbuf); free(vbuf); return rv; } /* parse arguments of delete command */ int rundelete(int argc, char **argv){ char *name, *key, *kbuf; int i, qdbm, kx, ksiz, rv; name = NULL; qdbm = FALSE; kx = FALSE; key = NULL; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ if(!strcmp(argv[i], "-qdbm")){ qdbm = TRUE; } else if(!strcmp(argv[i], "-kx")){ kx = TRUE; } else { usage(); } } else if(!name){ name = argv[i]; } else if(!key){ key = argv[i]; } else { usage(); } } if(!name || !key) usage(); if(kx){ kbuf = hextoobj(key, &ksiz); } else { kbuf = cbmemdup(key, -1); ksiz = strlen(kbuf); } if(kbuf){ rv = dodelete(name, qdbm, kbuf, ksiz); } else { fprintf(stderr, "%s: out of memory\n", progname); rv = 1; } free(kbuf); return rv; } /* parse arguments of fetch command */ int runfetch(int argc, char **argv){ char *name, *key, *kbuf; int i, qdbm, kx, ox, nb, ksiz, rv; name = NULL; qdbm = FALSE; kx = FALSE; ox = FALSE; nb = FALSE; key = NULL; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ if(!strcmp(argv[i], "-qdbm")){ qdbm = TRUE; } else if(!strcmp(argv[i], "-kx")){ kx = TRUE; } else if(!strcmp(argv[i], "-ox")){ ox = TRUE; } else if(!strcmp(argv[i], "-n")){ nb = TRUE; } else { usage(); } } else if(!name){ name = argv[i]; } else if(!key){ key = argv[i]; } else { usage(); } } if(!name || !key) usage(); if(kx){ kbuf = hextoobj(key, &ksiz); } else { kbuf = cbmemdup(key, -1); ksiz = strlen(kbuf); } if(kbuf){ rv = dofetch(name, qdbm, kbuf, ksiz, ox, nb); } else { fprintf(stderr, "%s: out of memory\n", progname); rv = 1; } free(kbuf); return rv; } /* parse arguments of list command */ int runlist(int argc, char **argv){ char *name; int i, qdbm, ox, rv; name = NULL; qdbm = FALSE; ox = FALSE; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ if(!strcmp(argv[i], "-qdbm")){ qdbm = TRUE; } else if(!strcmp(argv[i], "-ox")){ ox = TRUE; } else { usage(); } } else if(!name){ name = argv[i]; } else { usage(); } } if(!name) usage(); rv = dolist(name, qdbm, ox); return rv; } /* parse arguments of optimize command */ int runoptimize(int argc, char **argv){ char *name; int i, qdbm, rv; name = NULL; qdbm = FALSE; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ if(!strcmp(argv[i], "-qdbm")){ qdbm = TRUE; } else { usage(); } } else if(!name){ name = argv[i]; } else { usage(); } } if(!name) usage(); rv = dooptimize(name, qdbm); return rv; } /* print an error message */ void pgerror(const char *name){ fprintf(stderr, "%s: %s: %s\n", progname, name, gdbm_strerror(gdbm_errno)); } /* print an object */ void printobj(const char *obj, int size){ int i; for(i = 0; i < size; i++){ putchar(obj[i]); } } /* print an object as a hexadecimal string */ void printobjhex(const char *obj, int size){ int i; for(i = 0; i < size; i++){ printf("%s%02X", i > 0 ? " " : "", ((const unsigned char *)obj)[i]); } } /* perform create command */ int docreate(char *name, int qdbm, int bnum, int dnum, int sparse){ GDBM_FILE dbf; int rwmode; rwmode = GDBM_NEWDB | (sparse ? GDBM_SPARSE : 0); if(qdbm){ if(!(dbf = gdbm_open2(name, rwmode, 00644, bnum, dnum, ALIGNSIZ))){ pgerror(name); return 1; } } else { if(!(dbf = gdbm_open(name, 0, rwmode, 00644, NULL))){ pgerror(name); return 1; } } gdbm_close(dbf); return 0; } /* perform store command */ int dostore(char *name, int qdbm, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int ins){ GDBM_FILE dbf; datum key, content; int rv; if(qdbm){ if(!(dbf = gdbm_open2(name, GDBM_WRITER, 00644, -1, -1, ALIGNSIZ))){ pgerror(name); return 1; } } else { if(!(dbf = gdbm_open(name, 0, GDBM_WRITER, 00644, NULL))){ pgerror(name); return 1; } } key.dptr = (char *)kbuf; key.dsize = ksiz; content.dptr = (char *)vbuf; content.dsize = vsiz; rv = 0; if(gdbm_store(dbf, key, content, ins ? GDBM_INSERT : GDBM_REPLACE) != 0){ pgerror(name); rv = 1; } gdbm_close(dbf); return rv; } /* perform delete command */ int dodelete(char *name, int qdbm, const char *kbuf, int ksiz){ GDBM_FILE dbf; datum key; int rv; if(qdbm){ if(!(dbf = gdbm_open2(name, GDBM_WRITER, 00644, -1, -1, ALIGNSIZ))){ pgerror(name); return 1; } } else { if(!(dbf = gdbm_open(name, 0, GDBM_WRITER, 00644, NULL))){ pgerror(name); return 1; } } key.dptr = (char *)kbuf; key.dsize = ksiz; if(gdbm_delete(dbf, key) == 0){ rv = 0; } else { pgerror(name); rv = 1; } gdbm_close(dbf); return rv; } /* perform fetch command */ int dofetch(char *name, int qdbm, const char *kbuf, int ksiz, int ox, int nb){ GDBM_FILE dbf; datum key, content; int rv; if(qdbm){ if(!(dbf = gdbm_open2(name, GDBM_READER, 00644, -1, -1, -1))){ pgerror(name); return 1; } } else { if(!(dbf = gdbm_open(name, 0, GDBM_READER, 00644, NULL))){ pgerror(name); return 1; } } key.dptr = (char *)kbuf; key.dsize = ksiz; content = gdbm_fetch(dbf, key); if(content.dptr){ if(ox){ printobjhex(content.dptr, content.dsize); } else { printobj(content.dptr, content.dsize); } if(!nb) putchar('\n'); rv = 0; free(content.dptr); } else { pgerror(name); rv = 1; } gdbm_close(dbf); return rv; } /* perform list command */ int dolist(char *name, int qdbm, int ox){ GDBM_FILE dbf; datum key, val; if(qdbm){ if(!(dbf = gdbm_open2(name, GDBM_READER, 00644, -1, -1, -1))){ pgerror(name); return 1; } } else { if(!(dbf = gdbm_open(name, 0, GDBM_READER, 00644, NULL))){ pgerror(name); return 1; } } for(key = gdbm_firstkey(dbf); key.dptr != NULL; key = gdbm_nextkey(dbf, key)){ val = gdbm_fetch(dbf, key); if(!val.dptr){ free(key.dptr); break; } if(ox){ printobjhex(key.dptr, key.dsize); putchar('\t'); printobjhex(val.dptr, val.dsize); } else { printobj(key.dptr, key.dsize); putchar('\t'); printobj(val.dptr, val.dsize); } putchar('\n'); free(val.dptr); free(key.dptr); } gdbm_close(dbf); return 0; } /* perform optimize command */ int dooptimize(char *name, int qdbm){ GDBM_FILE dbf; int rv; if(qdbm){ if(!(dbf = gdbm_open2(name, GDBM_WRITER, 00644, -1, -1, ALIGNSIZ))){ pgerror(name); return 1; } } else { if(!(dbf = gdbm_open(name, 0, GDBM_WRITER, 00644, NULL))){ pgerror(name); return 1; } } rv = 0; if(gdbm_reorganize(dbf) != 0){ pgerror(name); rv = 1; } gdbm_close(dbf); return rv; } /* END OF FILE */ qdbm-1.8.78/odmgr.c0000644000175000017500000006436010610627747013043 0ustar mikiomikio/************************************************************************************************* * Utility for debugging Odeum and its applications * Copyright (C) 2000-2007 Mikio Hirabayashi * This file is part of QDBM, Quick Database Manager. * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU * Lesser General Public License as published by the Free Software Foundation; either version * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * You should have received a copy of the GNU Lesser General Public License along with QDBM; if * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. *************************************************************************************************/ #include #include #include #include #include #include #undef TRUE #define TRUE 1 /* boolean true */ #undef FALSE #define FALSE 0 /* boolean false */ #define MAXSRCHWORDS 256 /* max number of search words */ #define WOCCRPOINT 10000 /* points per occurence */ #define MAXKEYWORDS 8 /* max number of keywords */ #define SUMMARYWIDTH 16 /* width of each phrase in a summary */ #define MAXSUMMARY 128 /* max number of words in a summary */ /* for RISC OS */ #if defined(__riscos__) || defined(__riscos) #include int __riscosify_control = __RISCOSIFY_NO_PROCESS; #endif /* global variables */ const char *progname; /* program name */ /* function prototypes */ int main(int argc, char **argv); void usage(void); char *readstdin(int *sp); void otcb(const char *fname, ODEUM *odeum, const char *msg); int runcreate(int argc, char **argv); int runput(int argc, char **argv); int runout(int argc, char **argv); int runget(int argc, char **argv); int runsearch(int argc, char **argv); int runlist(int argc, char **argv); int runoptimize(int argc, char **argv); int runinform(int argc, char **argv); int runmerge(int argc, char **argv); int runremove(int argc, char **argv); int runbreak(int argc, char **argv); void pdperror(const char *name); void printdoc(const ODDOC *doc, int tb, int hb, int score, ODEUM *odeum, const CBLIST *skeys); char *docsummary(const ODDOC *doc, const CBLIST *kwords, int num, int hilight); CBMAP *listtomap(const CBLIST *list); int docreate(const char *name); int doput(const char *name, const char *text, const char *uri, const char *title, const char *author, const char *date, int wmax, int keep); int doout(const char *name, const char *uri, int id); int doget(const char *name, const char *uri, int id, int tb, int hb); int dosearch(const char *name, const char *text, int max, int or, int idf, int ql, int tb, int hb, int nb); int dolist(const char *name, int tb, int hb); int dooptimize(const char *name); int doinform(const char *name); int domerge(const char *name, const CBLIST *elems); int doremove(const char *name); int dobreak(const char *text, int hb, int kb, int sb); /* main routine */ int main(int argc, char **argv){ char *env; int rv; cbstdiobin(); progname = argv[0]; if((env = getenv("QDBMDBGFD")) != NULL) dpdbgfd = atoi(env); if(argc < 2) usage(); rv = 0; if(!strcmp(argv[1], "create")){ odsetotcb(otcb); rv = runcreate(argc, argv); } else if(!strcmp(argv[1], "put")){ odsetotcb(otcb); rv = runput(argc, argv); } else if(!strcmp(argv[1], "out")){ odsetotcb(otcb); rv = runout(argc, argv); } else if(!strcmp(argv[1], "get")){ rv = runget(argc, argv); } else if(!strcmp(argv[1], "search")){ rv = runsearch(argc, argv); } else if(!strcmp(argv[1], "list")){ rv = runlist(argc, argv); } else if(!strcmp(argv[1], "optimize")){ odsetotcb(otcb); rv = runoptimize(argc, argv); } else if(!strcmp(argv[1], "inform")){ rv = runinform(argc, argv); } else if(!strcmp(argv[1], "merge")){ odsetotcb(otcb); rv = runmerge(argc, argv); } else if(!strcmp(argv[1], "remove")){ rv = runremove(argc, argv); } else if(!strcmp(argv[1], "break")){ rv = runbreak(argc, argv); } else if(!strcmp(argv[1], "version") || !strcmp(argv[1], "--version")){ printf("Powered by QDBM version %s\n", dpversion); printf("Copyright (c) 2000-2007 Mikio Hirabayashi\n"); rv = 0; } else { usage(); } return rv; } /* print the usage and exit */ void usage(void){ fprintf(stderr, "%s: administration utility for Odeum\n", progname); fprintf(stderr, "\n"); fprintf(stderr, "usage:\n"); fprintf(stderr, " %s create name\n", progname); fprintf(stderr, " %s put [-uri str] [-title str] [-author str] [-date str]" " [-wmax num] [-keep] name [file]\n", progname); fprintf(stderr, " %s out [-id] name expr\n", progname); fprintf(stderr, " %s get [-id] [-t|-h] name expr\n", progname); fprintf(stderr, " %s search [-max num] [-or] [-idf] [-t|-h|-n] name words...\n", progname); fprintf(stderr, " %s list [-t|-h] name\n", progname); fprintf(stderr, " %s optimize name\n", progname); fprintf(stderr, " %s inform name\n", progname); fprintf(stderr, " %s merge name elems...\n", progname); fprintf(stderr, " %s remove name\n", progname); fprintf(stderr, " %s break [-h|-k|-s] [file]\n", progname); fprintf(stderr, " %s version\n", progname); fprintf(stderr, "\n"); exit(1); } /* read the standard input */ char *readstdin(int *sp){ char *buf; int i, blen, c; blen = 256; buf = cbmalloc(blen); for(i = 0; (c = getchar()) != EOF; i++){ if(i >= blen - 1) buf = cbrealloc(buf, blen *= 2); buf[i] = c; } buf[i] = '\0'; *sp = i; return buf; } /* report the outturn */ void otcb(const char *fname, ODEUM *odeum, const char *msg){ char *name; name = odname(odeum); printf("%s: %s: %s: %s\n", progname, fname, name, msg); free(name); } /* parse arguments of create command */ int runcreate(int argc, char **argv){ char *name; int i, rv; name = NULL; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ usage(); } else if(!name){ name = argv[i]; } else { usage(); } } if(!name) usage(); rv = docreate(name); return rv; } /* parse arguments of put command */ int runput(int argc, char **argv){ char *name, *file, *uri, *title, *author, *date, *text; int i, wmax, keep, size, rv; name = NULL; file = NULL; uri = NULL; title = NULL; author = NULL; date = NULL; wmax = -1; keep = FALSE; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ if(!strcmp(argv[i], "-uri")){ if(++i >= argc) usage(); uri = argv[i]; } else if(!strcmp(argv[i], "-uri")){ if(++i >= argc) usage(); uri = argv[i]; } else if(!strcmp(argv[i], "-title")){ if(++i >= argc) usage(); title = argv[i]; } else if(!strcmp(argv[i], "-author")){ if(++i >= argc) usage(); author = argv[i]; } else if(!strcmp(argv[i], "-date")){ if(++i >= argc) usage(); date = argv[i]; } else if(!strcmp(argv[i], "-wmax")){ if(++i >= argc) usage(); wmax = atoi(argv[i]); } else if(!strcmp(argv[i], "-keep")){ keep = TRUE; } else { usage(); } } else if(!name){ name = argv[i]; } else if(!file){ file = argv[i]; } else { usage(); } } if(!name) usage(); if(!uri) uri = file; if(!uri) usage(); if(file){ if(!(text = cbreadfile(file, &size))){ fprintf(stderr, "%s: %s: cannot open\n", progname, file); return 1; } } else { text = readstdin(&size); } rv = doput(name, text, uri, title, author, date, wmax, keep); free(text); return rv; } /* parse arguments of out command */ int runout(int argc, char **argv){ char *name, *expr; int i, ib, id, rv; name = NULL; expr = NULL; ib = FALSE; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ if(!strcmp(argv[i], "-id")){ ib = TRUE; } else { usage(); } } else if(!name){ name = argv[i]; } else if(!expr){ expr = argv[i]; } else { usage(); } } if(!name || !expr) usage(); id = -1; if(ib){ id = atoi(expr); if(id < 1) usage(); } rv = doout(name, expr, id); return rv; } /* parse arguments of get command */ int runget(int argc, char **argv){ char *name, *expr; int i, ib, tb, hb, id, rv; name = NULL; expr = NULL; ib = FALSE; tb = FALSE; hb = FALSE; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ if(!strcmp(argv[i], "-id")){ ib = TRUE; } else if(!strcmp(argv[i], "-t")){ tb = TRUE; } else if(!strcmp(argv[i], "-h")){ hb = TRUE; } else { usage(); } } else if(!name){ name = argv[i]; } else if(!expr){ expr = argv[i]; } else { usage(); } } if(!name || !expr) usage(); id = -1; if(ib){ id = atoi(expr); if(id < 1) usage(); } rv = doget(name, expr, id, tb, hb); return rv; } /* parse arguments of search command */ int runsearch(int argc, char **argv){ char *name, *srchwords[MAXSRCHWORDS]; int i, wnum, max, or, idf, ql, tb, hb, nb, rv; CBDATUM *text; name = NULL; wnum = 0; max = -1; or = FALSE; idf = FALSE; ql = FALSE; tb = FALSE; hb = FALSE; nb = FALSE; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ if(!strcmp(argv[i], "-max")){ if(++i >= argc) usage(); max = atoi(argv[i]); } else if(!strcmp(argv[i], "-or")){ or = TRUE; } else if(!strcmp(argv[i], "-idf")){ idf = TRUE; } else if(!strcmp(argv[i], "-ql")){ ql = TRUE; } else if(!strcmp(argv[i], "-t")){ tb = TRUE; } else if(!strcmp(argv[i], "-h")){ hb = TRUE; } else if(!strcmp(argv[i], "-n")){ nb = TRUE; } else { usage(); } } else if(!name){ name = argv[i]; } else if(wnum < MAXSRCHWORDS){ srchwords[wnum++] = argv[i]; } } if(!name) usage(); text = cbdatumopen(NULL, -1); for(i = 0; i < wnum; i++){ if(i > 0) cbdatumcat(text, " ", 1); cbdatumcat(text, srchwords[i], -1); } rv = dosearch(name, cbdatumptr(text), max, or, idf, ql, tb, hb, nb); cbdatumclose(text); return rv; } /* parse arguments of list command */ int runlist(int argc, char **argv){ char *name; int i, tb, hb, rv; name = NULL; tb = FALSE; hb = FALSE; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ if(!strcmp(argv[i], "-t")){ tb = TRUE; } else if(!strcmp(argv[i], "-h")){ hb = TRUE; } else { usage(); } } else if(!name){ name = argv[i]; } else { usage(); } } if(!name) usage(); rv = dolist(name, tb, hb); return rv; } /* parse arguments of optimize command */ int runoptimize(int argc, char **argv){ char *name; int i, rv; name = NULL; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ usage(); } else if(!name){ name = argv[i]; } else { usage(); } } if(!name) usage(); rv = dooptimize(name); return rv; } /* parse arguments of inform command */ int runinform(int argc, char **argv){ char *name; int i, rv; name = NULL; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ usage(); } else if(!name){ name = argv[i]; } else { usage(); } } if(!name) usage(); rv = doinform(name); return rv; } /* parse arguments of merge command */ int runmerge(int argc, char **argv){ char *name; CBLIST *elems; int i, rv; name = NULL; elems = cblistopen(); for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ usage(); } else if(!name){ name = argv[i]; } else { cblistpush(elems, argv[i], -1); } } if(!name) usage(); if(cblistnum(elems) < 1){ cblistclose(elems); usage(); } rv = domerge(name, elems); cblistclose(elems); return rv; } /* parse arguments of remove command */ int runremove(int argc, char **argv){ char *name; int i, rv; name = NULL; for(i = 2; i < argc; i++){ if(!name && argv[i][0] == '-'){ usage(); } else if(!name){ name = argv[i]; } else { usage(); } } if(!name) usage(); rv = doremove(name); return rv; } /* parse arguments of break command */ int runbreak(int argc, char **argv){ char *file, *text; int i, hb, kb, sb, size, rv; file = NULL; hb = FALSE; kb = FALSE; sb = FALSE; for(i = 2; i < argc; i++){ if(!file && argv[i][0] == '-'){ if(!strcmp(argv[i], "-h")){ hb = TRUE; } else if(!strcmp(argv[i], "-k")){ kb = TRUE; } else if(!strcmp(argv[i], "-s")){ sb = TRUE; } else { usage(); } } else if(!file){ file = argv[i]; } else { usage(); } } if(file){ if(!(text = cbreadfile(file, &size))){ fprintf(stderr, "%s: %s: cannot open\n", progname, file); return 1; } } else { text = readstdin(&size); } rv = dobreak(text, hb, kb, sb); free(text); return rv; } /* print an error message */ void pdperror(const char *name){ fprintf(stderr, "%s: %s: %s\n", progname, name, dperrmsg(dpecode)); } /* print the contents of a document */ void printdoc(const ODDOC *doc, int tb, int hb, int score, ODEUM *odeum, const CBLIST *skeys){ const CBLIST *words; CBMAP *scores; CBLIST *kwords; const char *title, *author, *word, *date; char *summary; int i, wsiz; title = oddocgetattr(doc, "title"); author = oddocgetattr(doc, "author"); date = oddocgetattr(doc, "date"); if(hb){ printf("ID: %d\n", oddocid(doc)); printf("URI: %s\n", oddocuri(doc)); if(title) printf("TITLE: %s\n", title); if(author) printf("AUTHOR: %s\n", author); if(date) printf("DATE: %s\n", date); if(score >= 0) printf("SCORE: %d\n", score); scores = oddocscores(doc, MAXKEYWORDS, odeum); kwords = cblistopen(); printf("KEYWORDS: "); cbmapiterinit(scores); while((word = cbmapiternext(scores, &wsiz)) != NULL){ if(cblistnum(kwords) > 0) printf(", "); printf("%s (%s)", word, cbmapget(scores, word, wsiz, NULL)); cblistpush(kwords, word, wsiz); } putchar('\n'); summary = docsummary(doc, skeys ? skeys : kwords, MAXSUMMARY, skeys != NULL); printf("SUMMARY: %s\n", summary); free(summary); cblistclose(kwords); cbmapclose(scores); printf("\n\n"); } else if(tb){ printf("%d\t%s\t%s\t%s\t%s\t%d\n", oddocid(doc), oddocuri(doc), title ? title : "", author ? author : "", date ? date : "", score); words = oddocnwords(doc); for(i = 0; i < cblistnum(words); i++){ word = cblistval(words, i, &wsiz); if(i > 0) putchar('\t'); printf("%s", word); } putchar('\n'); words = oddocawords(doc); for(i = 0; i < cblistnum(words); i++){ word = cblistval(words, i, &wsiz); if(i > 0) putchar('\t'); printf("%s", word); } putchar('\n'); } else { printf("%d\t%s\t%d\n", oddocid(doc), oddocuri(doc), score); } } /* get a list handle contains summary of a document */ char *docsummary(const ODDOC *doc, const CBLIST *kwords, int num, int hilight){ const CBLIST *nwords, *awords; CBMAP *kmap, *map; const char *normal, *asis; char *sbuf; int i, j, bsiz, ssiz, lnum, nwsiz, awsiz, pv, bi, first; bsiz = 256; sbuf = cbmalloc(bsiz); ssiz = 0; nwords = oddocnwords(doc); awords = oddocawords(doc); kmap = listtomap(kwords); map = listtomap(kwords); lnum = cblistnum(nwords); first = TRUE; for(i = 0; i < lnum && i < SUMMARYWIDTH; i++){ normal = cblistval(nwords, i, &nwsiz); asis = cblistval(awords, i, &awsiz); if(awsiz < 1) continue; cbmapout(map, normal, nwsiz); if(ssiz + awsiz + 16 >= bsiz){ bsiz = bsiz * 2 + awsiz; sbuf = cbrealloc(sbuf, bsiz); } if(!first) ssiz += sprintf(sbuf + ssiz, " "); if(hilight && normal[0] != '\0' && cbmapget(kmap, normal, nwsiz, NULL)){ ssiz += sprintf(sbuf + ssiz, "<<%s>>", asis); } else { ssiz += sprintf(sbuf + ssiz, "%s", asis); } first = FALSE; num--; } ssiz += sprintf(sbuf + ssiz, " ..."); pv = i; while(i < lnum){ if(cbmaprnum(map) < 1){ cbmapclose(map); map = listtomap(kwords); } normal = cblistval(nwords, i, &nwsiz); if(cbmapget(map, normal, nwsiz, NULL)){ bi = i - SUMMARYWIDTH / 2; bi = bi > pv ? bi : pv; for(j = bi; j < lnum && j <= bi + SUMMARYWIDTH; j++){ normal = cblistval(nwords, j, &nwsiz); asis = cblistval(awords, j, &awsiz); if(awsiz < 1) continue; cbmapout(map, normal, nwsiz); if(ssiz + awsiz + 16 >= bsiz){ bsiz = bsiz * 2 + awsiz; sbuf = cbrealloc(sbuf, bsiz); } ssiz += sprintf(sbuf + ssiz, " "); if(hilight && normal[0] != '\0' && cbmapget(kmap, normal, nwsiz, NULL)){ ssiz += sprintf(sbuf + ssiz, "<<%s>>", asis); } else { ssiz += sprintf(sbuf + ssiz, "%s", asis); } num--; } ssiz += sprintf(sbuf + ssiz, " ..."); i = j; pv = i; } else { i++; } if(num <= 0) break; } cbmapclose(map); cbmapclose(kmap); return sbuf; } /* get a map made from a list */ CBMAP *listtomap(const CBLIST *list){ CBMAP *map; const char *tmp; int i, tsiz; map = cbmapopen(); for(i = 0; i < cblistnum(list); i++){ tmp = cblistval(list, i, &tsiz); cbmapput(map, tmp, tsiz, "", 0, FALSE); } return map; } /* perform create command */ int docreate(const char *name){ ODEUM *odeum; if(!(odeum = odopen(name, OD_OWRITER | OD_OCREAT | OD_OTRUNC))){ pdperror(name); return 1; } if(!odclose(odeum)){ pdperror(name); return 1; } return 0; } /* perform put command */ int doput(const char *name, const char *text, const char *uri, const char *title, const char *author, const char *date, int wmax, int keep){ ODEUM *odeum; ODDOC *doc; CBLIST *awords; const char *asis; char *normal; int i; if(!(odeum = odopen(name, OD_OWRITER))){ pdperror(name); return 1; } doc = oddocopen(uri); if(title) oddocaddattr(doc, "title", title); if(author) oddocaddattr(doc, "author", author); if(date) oddocaddattr(doc, "date", date); awords = odbreaktext(text); for(i = 0; i < cblistnum(awords); i++){ asis = cblistval(awords, i, NULL); normal = odnormalizeword(asis); oddocaddword(doc, normal, asis); free(normal); } cblistclose(awords); if(!odput(odeum, doc, wmax, keep ? FALSE : TRUE)){ pdperror(name); oddocclose(doc); odclose(odeum); return 1; } oddocclose(doc); if(!odclose(odeum)){ pdperror(name); return 1; } return 0; } /* perform out command */ int doout(const char *name, const char *uri, int id){ ODEUM *odeum; if(!(odeum = odopen(name, OD_OWRITER))){ pdperror(name); return 1; } if(id > 0){ if(!odoutbyid(odeum, id)){ pdperror(name); odclose(odeum); return 1; } } else { if(!odout(odeum, uri)){ pdperror(name); odclose(odeum); return 1; } } if(!odclose(odeum)){ pdperror(name); return 1; } return 0; } /* perform get command */ int doget(const char *name, const char *uri, int id, int tb, int hb){ ODEUM *odeum; ODDOC *doc; if(!(odeum = odopen(name, OD_OREADER))){ pdperror(name); return 1; } if(id > 0){ if(!(doc = odgetbyid(odeum, id))){ pdperror(name); odclose(odeum); return 1; } } else { if(!(doc = odget(odeum, uri))){ pdperror(name); odclose(odeum); return 1; } } printdoc(doc, tb, hb, -1, odeum, NULL); oddocclose(doc); if(!odclose(odeum)){ pdperror(name); return 1; } return 0; } /* perform search command */ int dosearch(const char *name, const char *text, int max, int or, int idf, int ql, int tb, int hb, int nb){ ODEUM *odeum; CBLIST *awords, *nwords, *uris, *hits; ODPAIR *pairs, *last, *tmp; ODDOC *doc; const char *asis; char *normal, numbuf[32]; int i, j, pnum, lnum, hnum, tnum, shows; double ival; if(!(odeum = odopen(name, OD_OREADER))){ pdperror(name); return 1; } awords = odbreaktext(text); nwords = cblistopen(); uris = cblistopen(); hits = cblistopen(); last = NULL; lnum = 0; if(ql){ last= odquery(odeum, text, &lnum, NULL); } else { for(i = 0; i < cblistnum(awords); i++){ asis = cblistval(awords, i, NULL); normal = odnormalizeword(asis); cblistpush(nwords, normal, -1); if(strlen(normal) < 1){ free(normal); continue; } if(!(pairs = odsearch(odeum, normal, or ? max : -1, &pnum))){ pdperror(name); free(normal); continue; } if((hnum = odsearchdnum(odeum, normal)) < 0) hnum = 0; if(idf){ ival = odlogarithm(hnum); ival = (ival * ival) / 4.0; if(ival < 4.0) ival = 4.0; for(j = 0; j < pnum; j++){ pairs[j].score = (int)(pairs[j].score / ival); } } cblistpush(uris, normal, -1); sprintf(numbuf, "%d", hnum); cblistpush(hits, numbuf, -1); if(last){ if(or){ tmp = odpairsor(last, lnum, pairs, pnum, &tnum); } else { tmp = odpairsand(last, lnum, pairs, pnum, &tnum); } free(last); free(pairs); last = tmp; lnum = tnum; } else { last = pairs; lnum = pnum; } free(normal); } } if(hb){ printf("TOTAL: %d\n", lnum); printf("EACHWORD: "); } else { printf("%d", lnum); } for(i = 0; i < cblistnum(uris); i++){ if(hb){ if(i > 0) printf(", "); printf("%s(%s)", cblistval(uris, i, NULL), cblistval(hits, i, NULL)); } else { printf("\t%s\t%s", cblistval(uris, i, NULL), cblistval(hits, i, NULL)); } } putchar('\n'); if(hb) putchar('\n'); if(last){ if(max < 0) max = lnum; shows = 0; for(i = 0; i < lnum && shows < max; i++){ if(nb){ printf("%d\t%d\n", last[i].id, last[i].score); shows++; } else { if(!(doc = odgetbyid(odeum, last[i].id))) continue; printdoc(doc, tb, hb, last[i].score, odeum, nwords); oddocclose(doc); shows++; } } free(last); } cblistclose(uris); cblistclose(hits); cblistclose(nwords); cblistclose(awords); if(!odclose(odeum)){ pdperror(name); return 1; } return 0; } /* perform list command */ int dolist(const char *name, int tb, int hb){ ODEUM *odeum; ODDOC *doc; if(!(odeum = odopen(name, OD_OREADER))){ pdperror(name); return 1; } if(!oditerinit(odeum)){ odclose(odeum); pdperror(name); return 1; } while(TRUE){ if(!(doc = oditernext(odeum))){ if(dpecode == DP_ENOITEM) break; odclose(odeum); pdperror(name); return 1; } printdoc(doc, tb, hb, -1, odeum, NULL); oddocclose(doc); } if(!odclose(odeum)){ pdperror(name); return 1; } return 0; } /* perform optimize command */ int dooptimize(const char *name){ ODEUM *odeum; if(!(odeum = odopen(name, OD_OWRITER))){ pdperror(name); return 1; } if(!odoptimize(odeum)){ pdperror(name); odclose(odeum); return 1; } if(!odclose(odeum)){ pdperror(name); return 1; } return 0; } /* perform inform command */ int doinform(const char *name){ ODEUM *odeum; char *tmp; if(!(odeum = odopen(name, OD_OREADER))){ pdperror(name); return 1; } tmp = odname(odeum); printf("name: %s\n", tmp ? tmp : "(null)"); free(tmp); printf("file size: %.0f\n", odfsiz(odeum)); printf("index buckets: %d\n", odbnum(odeum)); printf("used buckets: %d\n", odbusenum(odeum)); printf("all documents: %d\n", oddnum(odeum)); printf("all words: %d\n", odwnum(odeum)); printf("inode number: %d\n", odinode(odeum)); printf("modified time: %.0f\n", (double)odmtime(odeum)); if(!odclose(odeum)){ pdperror(name); return 1; } return 0; } /* perform merge command */ int domerge(const char *name, const CBLIST *elems){ if(!odmerge(name, elems)){ pdperror(name); return 1; } return 0; } /* perform remove command */ int doremove(const char *name){ if(!odremove(name)){ pdperror(name); return 1; } return 0; } /* perform break command */ int dobreak(const char *text, int hb, int kb, int sb){ CBLIST *awords, *kwords; CBMAP *scores; ODDOC *doc; const char *asis; char *normal, *summary; int i, first; awords = odbreaktext(text); if(kb || sb){ doc = oddocopen(""); for(i = 0; i < cblistnum(awords); i++){ asis = cblistval(awords, i, NULL); normal = odnormalizeword(asis); oddocaddword(doc, normal, asis); free(normal); } scores = oddocscores(doc, MAXKEYWORDS, NULL); cbmapiterinit(scores); kwords = cbmapkeys(scores); if(kb){ for(i = 0; i < cblistnum(kwords); i++){ if(i > 0) putchar('\t'); printf("%s", cblistval(kwords, i, NULL)); } putchar('\n'); } else { summary = docsummary(doc, kwords, MAXSUMMARY, FALSE); printf("%s\n", summary); free(summary); } cblistclose(kwords); cbmapclose(scores); oddocclose(doc); } else if(hb){ printf("NWORDS: "); first = TRUE; for(i = 0; i < cblistnum(awords); i++){ asis = cblistval(awords, i, NULL); normal = odnormalizeword(asis); if(normal[0] == '\0'){ free(normal); continue; } if(!first) putchar(' '); first = FALSE; printf("%s", normal); free(normal); } putchar('\n'); printf("AWORDS: "); first = TRUE; for(i = 0; i < cblistnum(awords); i++){ asis = cblistval(awords, i, NULL); if(asis[0] == '\0') continue; if(!first) putchar(' '); first = FALSE; printf("%s", asis); } putchar('\n'); } else { for(i = 0; i < cblistnum(awords); i++){ asis = cblistval(awords, i, NULL); normal = odnormalizeword(asis); printf("%s\t%s\n", normal, asis); free(normal); } } cblistclose(awords); return 0; } /* END OF FILE */