/* * Copyright (c) 1995, 1996 Gunther Schadow. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "pg_config.h" IDENT("@(#) odbm-ctor.cc (Gunther Schadow) 12/19/96"); #pragma implementation "odbm.h" #include "odbm.h" #include #include #include #include /* * Single object access constructor */ odbm::odbm(char **k, char **str, void *scl, size_t scl_size, const char *dbfn, int mode, int cs, int bs) { keyp = k; strings = str; if(str == NULL) nostrings = 0; else nostrings = (char **)scl - str; scalars.dptr = (char *)scl; scalars.dsize = scl_size; object_cnt = NULL; dbfp = new GDBM_FILE; reopen.dbfn = strdup(dbfn); reopen.mode = mode; reopen.cachesize = cs; reopen.blocksize = bs; *dbfp = gdbm_open(reopen.dbfn, bs, mode, 0666, NULL); if(*dbfp == NULL) ERROS("gdbm_open: %s", gdbm_strerror(gdbm_errno)); else if(cs != default_cachesize) if(gdbm_setopt(*dbfp, GDBM_CACHESIZE, &cs, sizeof(cs)) == FAIL) ERROS("gdbm_setopt: %s", gdbm_strerror(gdbm_errno)); // NULLify the strings and the key *keyp = NULL; for(int i = 0; i < nostrings; i++) strings[i] = NULL; fltp = NULL; the_index = -1; the_cursor = (u_int)-1; } /* * Multi objects access constructor */ odbm::odbm(char **k, char **str, void *scl, size_t scl_size, odbm_file *dbf, unsigned int *obj_cnt, const char *dbfn, int mode, int cs, int bs) { keyp = k; strings = str; if(str == NULL) nostrings = 0; else nostrings = (char **)scl - str; scalars.dptr = (char *)scl; scalars.dsize = scl_size; reopen.dbfn = strdup(dbfn); reopen.mode = mode; reopen.cachesize = cs; reopen.blocksize = bs; dbfp = dbf; object_cnt = obj_cnt; if((*obj_cnt)++ == 0) { *dbfp = gdbm_open(reopen.dbfn, bs, mode, 0666, NULL); if(*dbfp == NULL) ERROS("gdbm_open: %s", gdbm_strerror(gdbm_errno)); else if(cs != default_cachesize) if(gdbm_setopt(*dbfp, GDBM_CACHESIZE, &cs, sizeof(cs)) == FAIL) ERROS("gdbm_setopt: %s", gdbm_strerror(gdbm_errno)); } key.dptr = NULL; data.dptr = NULL; // NULLify the strings and the key *keyp = NULL; for(int i = 0; i < nostrings; i++) strings[i] = NULL; fltp = NULL; the_index = -1; the_cursor = (u_int)-1; } /* * destructor */ odbm::~odbm() { if(*keyp != &key.dptr[1] && *keyp != NULL) delete [] *keyp; if(key.dptr != NULL) delete [] key.dptr; for(int i = 0; i < nostrings; i++) { if(strings[i] != NULL && !(data.dptr <= strings[i] && strings[i] < data.dptr + data.dsize)) delete [] strings[i]; } if(data.dptr != NULL) delete [] data.dptr; if(object_cnt != NULL) { if(--*object_cnt == 0) gdbm_close(*dbfp); } else { gdbm_close(*dbfp); delete dbfp; } delete [] reopen.dbfn; if(fltp != NULL) delete fltp; } /* * free * * Free a string, testing if it is outside of the current data * (or key) block. */ void odbm::free(void *p) { if(p == NULL) return; else if(p == &key.dptr[1]) return; if((data.dptr <= (char *)p) && ((char *)p < (data.dptr + data.dsize))) return; else ::free(p); } /* * Free any strings outside of the current data block. */ void odbm::free() { free(*keyp); *keyp = NULL; for(int i = 0; i < nostrings; i++) { free(strings[i]); strings[i] = NULL; } the_index = -1; the_cursor = (u_int)-1; } /* * Copy constructor and assignment operator */ odbm::odbm(const odbm &x) { // propagate gdbm file handle WARNING: copying a writer will fail! reopen = x.reopen; reopen.dbfn = strdup(reopen.dbfn); dbfp = x.dbfp; object_cnt = x.object_cnt; if(object_cnt == NULL) { // x is in single object access mode *dbfp = gdbm_open(reopen.dbfn, reopen.blocksize, reopen.mode, 0666, NULL); if(*dbfp == NULL) ERROS("gdbm_open: %s", gdbm_strerror(gdbm_errno)); else if(reopen.cachesize != default_cachesize) if(gdbm_setopt(*dbfp, GDBM_CACHESIZE, &reopen.cachesize, sizeof(reopen.cachesize)) == FAIL) ERROS("gdbm_setopt: %s", gdbm_strerror(gdbm_errno)); } else // x is in multi objects access mode (*object_cnt)++; nostrings = x.nostrings; indices = x.indices; // map references to derived object int diff = ((char *)this) - ((char *)&x); keyp = (char **)(((char *)x.keyp) + diff); strings = (char **)(((char *)x.strings) + diff); scalars.dsize = x.scalars.dsize; scalars.dptr = x.scalars.dptr + diff; // put all data of x into the block x.update_key(); x.build_data(); // copy and set the key key = x.key; key.dptr = strdup(key.dptr); *keyp = (char *)parse_key(); // copy and set the data data.dsize = x.data.dsize; data.dptr = new char [data.dsize]; memcpy(data.dptr, x.data.dptr, data.dsize); parse_data(); if(x.fltp != NULL) fltp = new filter(fltp); else fltp = NULL; the_index = x.the_index; the_cursor = x.the_cursor; } /* * since the assignment operator is called only for a valid object, * the work here is rather simple */ odbm &odbm::operator = (const odbm &x) { // delete old key and strings if necessary if(*keyp != &key.dptr[1] && *keyp != NULL) delete [] *keyp; if(key.dptr != NULL) delete [] key.dptr; for(int i = 0; i < nostrings; i++) { if(strings[i] != NULL && !(data.dptr <= strings[i] && strings[i] < data.dptr + data.dsize)) delete [] strings[i]; } if(data.dptr != NULL) delete [] data.dptr; // put all data of x into the block x.update_key(); x.build_data(); // copy and set the key key = x.key; key.dptr = strdup(key.dptr); *keyp = (char *)parse_key(); // copy and set the data data.dsize = x.data.dsize; data.dptr = new char [data.dsize]; memcpy(data.dptr, x.data.dptr, data.dsize); parse_data(); if(fltp != NULL) delete fltp; if(x.fltp != NULL) fltp = new filter(fltp); else fltp = NULL; the_index = x.the_index; the_cursor = x.the_cursor; return *this; }