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

📄 tcutil.c

📁 Tokyo Cabinet的Tokyo Cabinet 是一个DBM的实现。这里的数据库由一系列key-value对的记录构成。key和value都可以是任意长度的字节序列,既可以是二进制也可以是字符
💻 C
📖 第 1 页 / 共 5 页
字号:
    uint32_t rhash = rec->ksiz & ~TCMAPKMAXSIZ;    uint32_t rksiz = rec->ksiz & TCMAPKMAXSIZ;    if(hash > rhash){      rec = rec->left;    } else if(hash < rhash){      rec = rec->right;    } else {      char *dbuf = (char *)rec + sizeof(*rec);      int kcmp = TCKEYCMP(kbuf, ksiz, dbuf, rksiz);      if(kcmp < 0){        rec = rec->left;      } else if(kcmp > 0){        rec = rec->right;      } else {        *sp = rec->vsiz;        return dbuf + rksiz + TCALIGNPAD(rksiz);      }    }  }  return NULL;}/* Retrieve a string record in a map object. */const char *tcmapget2(const TCMAP *map, const char *kstr){  assert(map && kstr);  int ksiz = strlen(kstr);  if(ksiz > TCMAPKMAXSIZ) ksiz = TCMAPKMAXSIZ;  uint32_t hash;  TCMAPHASH1(hash, kstr, ksiz);  TCMAPREC *rec = map->buckets[hash%map->bnum];  TCMAPHASH2(hash, kstr, ksiz);  hash &= ~TCMAPKMAXSIZ;  while(rec){    uint32_t rhash = rec->ksiz & ~TCMAPKMAXSIZ;    uint32_t rksiz = rec->ksiz & TCMAPKMAXSIZ;    if(hash > rhash){      rec = rec->left;    } else if(hash < rhash){      rec = rec->right;    } else {      char *dbuf = (char *)rec + sizeof(*rec);      int kcmp = TCKEYCMP(kstr, ksiz, dbuf, rksiz);      if(kcmp < 0){        rec = rec->left;      } else if(kcmp > 0){        rec = rec->right;      } else {        return dbuf + rksiz + TCALIGNPAD(rksiz);      }    }  }  return NULL;}/* Move a record to the edge of a map object. */bool tcmapmove(TCMAP *map, const void *kbuf, int ksiz, bool head){  assert(map && kbuf && ksiz >= 0);  if(ksiz > TCMAPKMAXSIZ) ksiz = TCMAPKMAXSIZ;  uint32_t hash;  TCMAPHASH1(hash, kbuf, ksiz);  TCMAPREC *rec = map->buckets[hash%map->bnum];  TCMAPHASH2(hash, kbuf, ksiz);  hash &= ~TCMAPKMAXSIZ;  while(rec){    uint32_t rhash = rec->ksiz & ~TCMAPKMAXSIZ;    uint32_t rksiz = rec->ksiz & TCMAPKMAXSIZ;    if(hash > rhash){      rec = rec->left;    } else if(hash < rhash){      rec = rec->right;    } else {      char *dbuf = (char *)rec + sizeof(*rec);      int kcmp = TCKEYCMP(kbuf, ksiz, dbuf, rksiz);      if(kcmp < 0){        rec = rec->left;      } else if(kcmp > 0){        rec = rec->right;      } else {        if(head){          if(map->first == rec) return true;          if(map->last == rec) map->last = rec->prev;          if(rec->prev) rec->prev->next = rec->next;          if(rec->next) rec->next->prev = rec->prev;          rec->prev = NULL;          rec->next = map->first;          map->first->prev = rec;          map->first = rec;        } else {          if(map->last == rec) return true;          if(map->first == rec) map->first = rec->next;          if(rec->prev) rec->prev->next = rec->next;          if(rec->next) rec->next->prev = rec->prev;          rec->prev = map->last;          rec->next = NULL;          map->last->next = rec;          map->last = rec;        }        return true;      }    }  }  return false;}/* Move a string record to the edge of a map object. */bool tcmapmove2(TCMAP *map, const char *kstr, bool head){  assert(map && kstr);  return tcmapmove(map, kstr, strlen(kstr), head);}/* Initialize the iterator of a map object. */void tcmapiterinit(TCMAP *map){  assert(map);  map->cur = map->first;}/* Get the next key of the iterator of a map object. */const void *tcmapiternext(TCMAP *map, int *sp){  assert(map && sp);  TCMAPREC *rec;  if(!map->cur) return NULL;  rec = map->cur;  map->cur = rec->next;  *sp = rec->ksiz & TCMAPKMAXSIZ;  return (char *)rec + sizeof(*rec);}/* Get the next key string of the iterator of a map object. */const char *tcmapiternext2(TCMAP *map){  assert(map);  TCMAPREC *rec;  if(!map->cur) return NULL;  rec = map->cur;  map->cur = rec->next;  return (char *)rec + sizeof(*rec);}/* Get the number of records stored in a map object. */uint64_t tcmaprnum(const TCMAP *map){  assert(map);  return map->rnum;}/* Get the total size of memory used in a map object. */uint64_t tcmapmsiz(const TCMAP *map){  assert(map);  return map->msiz + map->rnum * (sizeof(*map->first) + sizeof(void *)) +    map->bnum * sizeof(void *);}/* Create a list object containing all keys in a map object. */TCLIST *tcmapkeys(const TCMAP *map){  assert(map);  TCLIST *list = tclistnew2(map->rnum);  TCMAPREC *rec = map->first;  while(rec){    char *dbuf = (char *)rec + sizeof(*rec);    TCLISTPUSH(list, dbuf, rec->ksiz & TCMAPKMAXSIZ);    rec = rec->next;  }  return list;}/* Create a list object containing all values in a map object. */TCLIST *tcmapvals(const TCMAP *map){  assert(map);  TCLIST *list = tclistnew2(map->rnum);  TCMAPREC *rec = map->first;  while(rec){    char *dbuf = (char *)rec + sizeof(*rec);    uint32_t rksiz = rec->ksiz & TCMAPKMAXSIZ;    TCLISTPUSH(list, dbuf + rksiz + TCALIGNPAD(rksiz), rec->vsiz);    rec = rec->next;  }  return list;}/* Add an integer to a record in a map object. */int tcmapaddint(TCMAP *map, const void *kbuf, int ksiz, int num){  assert(map && kbuf && ksiz >= 0);  if(ksiz > TCMAPKMAXSIZ) ksiz = TCMAPKMAXSIZ;  uint32_t hash;  TCMAPHASH1(hash, kbuf, ksiz);  int bidx = hash % map->bnum;  TCMAPREC *rec = map->buckets[bidx];  TCMAPREC **entp = map->buckets + bidx;  TCMAPHASH2(hash, kbuf, ksiz);  hash &= ~TCMAPKMAXSIZ;  while(rec){    uint32_t rhash = rec->ksiz & ~TCMAPKMAXSIZ;    uint32_t rksiz = rec->ksiz & TCMAPKMAXSIZ;    if(hash > rhash){      entp = &(rec->left);      rec = rec->left;    } else if(hash < rhash){      entp = &(rec->right);      rec = rec->right;    } else {      char *dbuf = (char *)rec + sizeof(*rec);      int kcmp = TCKEYCMP(kbuf, ksiz, dbuf, rksiz);      if(kcmp < 0){        entp = &(rec->left);        rec = rec->left;      } else if(kcmp > 0){        entp = &(rec->right);        rec = rec->right;      } else {        if(rec->vsiz != sizeof(num)) return INT_MIN;        int *resp = (int *)(dbuf + ksiz + TCALIGNPAD(ksiz));        return *resp += num;      }    }  }  int psiz = TCALIGNPAD(ksiz);  TCMALLOC(rec, sizeof(*rec) + ksiz + psiz + sizeof(num) + 1);  char *dbuf = (char *)rec + sizeof(*rec);  memcpy(dbuf, kbuf, ksiz);  dbuf[ksiz] = '\0';  rec->ksiz = ksiz | hash;  memcpy(dbuf + ksiz + psiz, &num, sizeof(num));  dbuf[ksiz+psiz+sizeof(num)] = '\0';  rec->vsiz = sizeof(num);  rec->left = NULL;  rec->right = NULL;  rec->prev = map->last;  rec->next = NULL;  *entp = rec;  if(!map->first) map->first = rec;  if(map->last) map->last->next = rec;  map->last = rec;  map->rnum++;  return num;}/* Add a real number to a record in a map object. */double tcmapadddouble(TCMAP *map, const void *kbuf, int ksiz, double num){  assert(map && kbuf && ksiz >= 0);  if(ksiz > TCMAPKMAXSIZ) ksiz = TCMAPKMAXSIZ;  uint32_t hash;  TCMAPHASH1(hash, kbuf, ksiz);  int bidx = hash % map->bnum;  TCMAPREC *rec = map->buckets[bidx];  TCMAPREC **entp = map->buckets + bidx;  TCMAPHASH2(hash, kbuf, ksiz);  hash &= ~TCMAPKMAXSIZ;  while(rec){    uint32_t rhash = rec->ksiz & ~TCMAPKMAXSIZ;    uint32_t rksiz = rec->ksiz & TCMAPKMAXSIZ;    if(hash > rhash){      entp = &(rec->left);      rec = rec->left;    } else if(hash < rhash){      entp = &(rec->right);      rec = rec->right;    } else {      char *dbuf = (char *)rec + sizeof(*rec);      int kcmp = TCKEYCMP(kbuf, ksiz, dbuf, rksiz);      if(kcmp < 0){        entp = &(rec->left);        rec = rec->left;      } else if(kcmp > 0){        entp = &(rec->right);        rec = rec->right;      } else {        if(rec->vsiz != sizeof(num)) return nan("");        double *resp = (double *)(dbuf + ksiz + TCALIGNPAD(ksiz));        return *resp += num;      }    }  }  int psiz = TCALIGNPAD(ksiz);  TCMALLOC(rec, sizeof(*rec) + ksiz + psiz + sizeof(num) + 1);  char *dbuf = (char *)rec + sizeof(*rec);  memcpy(dbuf, kbuf, ksiz);  dbuf[ksiz] = '\0';  rec->ksiz = ksiz | hash;  memcpy(dbuf + ksiz + psiz, &num, sizeof(num));  dbuf[ksiz+psiz+sizeof(num)] = '\0';  rec->vsiz = sizeof(num);  rec->left = NULL;  rec->right = NULL;  rec->prev = map->last;  rec->next = NULL;  *entp = rec;  if(!map->first) map->first = rec;  if(map->last) map->last->next = rec;  map->last = rec;  map->rnum++;  return num;}/* Clear a map object. */void tcmapclear(TCMAP *map){  assert(map);  TCMAPREC *rec = map->first;  while(rec){    TCMAPREC *next = rec->next;    TCFREE(rec);    rec = next;  }  TCMAPREC **buckets = map->buckets;  int bnum = map->bnum;  for(int i = 0; i < bnum; i++){    buckets[i] = NULL;  }  map->first = NULL;  map->last = NULL;  map->cur = NULL;  map->rnum = 0;  map->msiz = 0;}/* Remove front records of a map object. */void tcmapcutfront(TCMAP *map, int num){  assert(map && num >= 0);  tcmapiterinit(map);  while(num-- > 0){    int ksiz;    const char *kbuf = tcmapiternext(map, &ksiz);    if(!kbuf) break;    tcmapout(map, kbuf, ksiz);  }}/* Serialize a map object into a byte array. */void *tcmapdump(const TCMAP *map, int *sp){  assert(map && sp);  int tsiz = 0;  TCMAPREC *rec = map->first;  while(rec){    tsiz += (rec->ksiz & TCMAPKMAXSIZ) + rec->vsiz + sizeof(int) * 2;    rec = rec->next;  }  char *buf;  TCMALLOC(buf, tsiz + 1);  char *wp = buf;  rec = map->first;  while(rec){    const char *kbuf = (char *)rec + sizeof(*rec);    int ksiz = rec->ksiz & TCMAPKMAXSIZ;    const char *vbuf = kbuf + ksiz + TCALIGNPAD(ksiz);    int vsiz = rec->vsiz;    int step;    TCSETVNUMBUF(step, wp, ksiz);    wp += step;    memcpy(wp, kbuf, ksiz);    wp += ksiz;    TCSETVNUMBUF(step, wp, vsiz);    wp += step;    memcpy(wp, vbuf, vsiz);    wp += vsiz;    rec = rec->next;  }  *sp = wp - buf;  return buf;}/* Create a map object from a serialized byte array. */TCMAP *tcmapload(const void *ptr, int size){  assert(ptr && size >= 0);  TCMAP *map = tcmapnew2(tclmin(size / 6 + 1, TCMAPDEFBNUM));  const char *rp = ptr;  const char *ep = (char *)ptr + size;  while(rp < ep){    int step, ksiz, vsiz;    TCREADVNUMBUF(rp, ksiz, step);    rp += step;    const char *kbuf = rp;    rp += ksiz;    TCREADVNUMBUF(rp, vsiz, step);    rp += step;    tcmapputkeep(map, kbuf, ksiz, rp, vsiz);    rp += vsiz;  }  return map;}/************************************************************************************************* * hash map (for experts) *************************************************************************************************//* Store a record and make it semivolatile in a map object. */void tcmapput3(TCMAP *map, const void *kbuf, int ksiz, const char *vbuf, int vsiz){  assert(map && kbuf && ksiz >= 0 && vbuf && vsiz >= 0);  if(ksiz > TCMAPKMAXSIZ) ksiz = TCMAPKMAXSIZ;  uint32_t hash;  TCMAPHASH1(hash, kbuf, ksiz);  int bidx = hash % map->bnum;  TCMAPREC *rec = map->buckets[bidx];  TCMAPREC **entp = map->buckets + bidx;  TCMAPHASH2(hash, kbuf, ksiz);  hash &= ~TCMAPKMAXSIZ;  while(rec){    uint32_t rhash = rec->ksiz & ~TCMAPKMAXSIZ;    uint32_t rksiz = rec->ksiz & TCMAPKMAXSIZ;    if(hash > rhash){      entp = &(rec->left);      rec = rec->left;    } else if(hash < rhash){      entp = &(rec->right);      rec = rec->right;    } else {      char *dbuf = (char *)rec + sizeof(*rec);      int kcmp = TCKEYCMP(kbuf, ksiz, dbuf, rksiz);      if(kcmp < 0){        entp = &(rec->left);        rec = rec->left;      } else if(kcmp > 0){        entp = &(rec->right);        rec = rec->right;      } else {        map->msiz += vsiz - rec->vsiz;        int psiz = TCALIGNPAD(ksiz);        if(vsiz > rec->vsiz){          TCMAPREC *old = rec;          TCREALLOC(rec, rec, sizeof(*rec) + ksiz + psiz + vsiz + 1);          if(rec != old){            if(map->first == old) map->first = rec;            if(map->last == old) map->last = rec;            if(map->cur == old) map->cur = rec;            *entp = rec;            if(rec->prev) rec->prev->next = rec;            if(rec->next) rec->next->prev = rec;            dbuf = (char *)rec + sizeof(*rec);          }        }        memcpy(dbuf + ksiz + psiz, vbuf, vsiz);        dbuf[ksiz+psiz+vsiz] = '\0';        rec->vsiz = vsiz;        if(map->last != rec){          if(map->first == rec) map->first = rec->next;          if(rec->prev) rec->prev->next = rec->next;          if(rec->next) rec->next->prev = rec->prev;          rec->prev = map->last;          rec->next = NULL;

⌨️ 快捷键说明

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