⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cabin.c

📁 harvest是一个下载html网页得机器人
💻 C
📖 第 1 页 / 共 3 页
字号:
/************************************************************************************************* * Implementation of Cabin *                                                      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 "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_DATUMUNIT   16                /* allocation unit size of a datum handle */#define CB_LISTUNIT    64                /* allocation unit number of a list handle */#define CB_MAPBNUM     8191              /* bucket size of a map handle */#define CB_MSGBUFSIZ   256               /* size of a buffer for log message */#define CB_IOBUFSIZ    4096              /* size of an I/O buffer */#define CB_VNUMBUFSIZ  8                 /* size of a buffer for variable length number *//* private function prototypes */static void cbmyfatal(const char *message);static void cbggchandler(void);static void cbggckeeper(void *ptr, void *func);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 cbfirsthash(const char *kbuf, int ksiz);static int cbsecondhash(const char *kbuf, int ksiz);static int cbkeycmp(const char *abuf, int asiz, const char *bbuf, int bsiz);static int cbsetvnumbuf(char *buf, int num);static int cbreadvnumbuf(const char *buf, int size, int *sp);/************************************************************************************************* * 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);  if(!(p = malloc(size))){    if(cbfatalfunc){      cbfatalfunc("out of memory");    } else {      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))){    if(cbfatalfunc){      cbfatalfunc("out of memory");    } else {      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);  p = cbmalloc(size + 1);  memcpy(p, ptr, size);  p[size] = '\0';  return p;}/* 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, (void *)func);}/* 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;  swap = cbmalloc(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;  swap = cbmalloc(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;  swap = cbmalloc(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);  pswap = cbmalloc(size);  vswap = cbmalloc(size);  cbqsortsub(base, nmemb, size, pswap, vswap, compar);  free(vswap);  free(pswap);}/* Get a datum handle. */CBDATUM *cbdatumopen(const char *ptr, int size){  CBDATUM *datum;  datum = cbmalloc(sizeof(*datum));  datum->dptr = cbmalloc(CB_DATUMUNIT);  datum->dsize = 0;  datum->asize = CB_DATUMUNIT;  if(ptr) cbdatumcat(datum, ptr, size);  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;    datum->dptr = cbrealloc(datum->dptr, datum->asize);  }  memmove(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;      datum->dptr = cbrealloc(datum->dptr, datum->asize);    }    memset(datum->dptr + datum->dsize, 0, (size - datum->dsize) + 1);    datum->dsize = size;  }}/* Get a list handle. */CBLIST *cblistopen(void){  CBLIST *list;  list = cbmalloc(sizeof(*list));  list->anum = CB_LISTUNIT;  list->array = cbmalloc(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);  newlist = cblistopen();  for(i = 0; i < cblistnum(list); i++){    val = cblistval(list, i, &size);    cblistpush(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;    list->array = cbrealloc(list->array, list->anum * sizeof(list->array[0]));  }  list->array[index].dptr = cbmemdup(ptr, size);  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;      list->array = cbrealloc(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;  list->array[index].dptr = cbmemdup(ptr, size);  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;    list->array = cbrealloc(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));  list->array[index].dptr = cbmemdup(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;  memmove(list->array + index, list->array + index + 1,          sizeof(list->array[0]) * (list->start + list->num - index));  list->num--;  return dptr;}/* Sort elements of a list in lexical order. */void cblistsort(CBLIST *list){  assert(list);  cbqsort(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);  key.dptr = cbmemdup(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 = cblistnum(list);  vnumsiz = cbsetvnumbuf(vnumbuf, ln);  buf = cbmalloc(vnumsiz + 1);  memcpy(buf, vnumbuf, vnumsiz);  bsiz = vnumsiz;  for(i = 0; i < ln; i++){    vbuf = cblistval(list, i, &vsiz);    vnumsiz = cbsetvnumbuf(vnumbuf, vsiz);    buf = cbrealloc(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, step, ln, vsiz;  assert(ptr && size >= 0);  list = cblistopen();  rp = ptr;  ln = cbreadvnumbuf(rp, size, &step);  rp += step;  size -= step;  if(ln > size) return list;  for(i = 0; i < ln; i++){    if(size < 1) break;    vsiz = cbreadvnumbuf(rp, size, &step);    rp += step;    size -= step;    if(vsiz > size) break;    cblistpush(list, rp, vsiz);    rp += vsiz;  }  return list;}/* Get a map handle. */CBMAP *cbmapopen(void){  CBMAP *map;  int i;  map = cbmalloc(sizeof(*map));  map->buckets = cbmalloc(sizeof(map->buckets[0]) * CB_MAPBNUM);  for(i = 0; i < CB_MAPBNUM; i++){    map->buckets[i] = NULL;  }  map->first = NULL;  map->last = NULL;  map->cur = NULL;  map->rnum = 0;  return map;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -