📄 tcutil.c
字号:
/* Create a map object with specifying the number of the buckets. */TCMAP *tcmapnew2(uint32_t bnum){ if(bnum < 1) bnum = 1; TCMAP *map; TCMALLOC(map, sizeof(*map)); TCMAPREC **buckets; if(bnum >= TCMAPZMMINSIZ / sizeof(*buckets)){ buckets = tczeromap(bnum * sizeof(*buckets)); } else { TCCALLOC(buckets, bnum, sizeof(*buckets)); } map->buckets = buckets; map->first = NULL; map->last = NULL; map->cur = NULL; map->bnum = bnum; map->rnum = 0; map->msiz = 0; return map;}/* Copy a map object. */TCMAP *tcmapdup(const TCMAP *map){ assert(map); TCMAP *nmap = tcmapnew2(tclmax(tclmax(map->bnum, map->rnum), TCMAPBNUM)); TCMAPREC *rec = map->first; while(rec){ char *dbuf = (char *)rec + sizeof(*rec); tcmapput(nmap, dbuf, rec->ksiz, dbuf + rec->ksiz + TCALIGNPAD(rec->ksiz), rec->vsiz); rec = rec->next; } return nmap;}/* Close a map object. */void tcmapdel(TCMAP *map){ assert(map); TCMAPREC *rec = map->first; while(rec){ TCMAPREC *next = rec->next; TCFREE(rec); rec = next; } if(map->bnum >= TCMAPZMMINSIZ / sizeof(map->buckets[0])){ tczerounmap(map->buckets); } else { TCFREE(map->buckets); } TCFREE(map);}/* Store a record into a map object. */void tcmapput(TCMAP *map, const void *kbuf, int ksiz, const void *vbuf, int vsiz){ assert(map && kbuf && ksiz >= 0 && vbuf && vsiz >= 0); unsigned int hash; TCMAPHASH1(hash, kbuf, ksiz); int bidx = hash % map->bnum; TCMAPREC *rec = map->buckets[bidx]; TCMAPREC **entp = map->buckets + bidx; TCMAPHASH2(hash, kbuf, ksiz); while(rec){ if(hash > rec->hash){ entp = &(rec->left); rec = rec->left; } else if(hash < rec->hash){ entp = &(rec->right); rec = rec->right; } else { char *dbuf = (char *)rec + sizeof(*rec); int kcmp = TCKEYCMP(kbuf, ksiz, dbuf, rec->ksiz); 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; if(*entp == old) *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; return; } } } int psiz = TCALIGNPAD(ksiz); map->msiz += ksiz + vsiz; TCMALLOC(rec, sizeof(*rec) + ksiz + psiz + vsiz + 1); char *dbuf = (char *)rec + sizeof(*rec); memcpy(dbuf, kbuf, ksiz); dbuf[ksiz] = '\0'; rec->ksiz = ksiz; memcpy(dbuf + ksiz + psiz, vbuf, vsiz); dbuf[ksiz+psiz+vsiz] = '\0'; rec->vsiz = vsiz; rec->hash = hash; 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++;}/* Store a string record into a map object. */void tcmapput2(TCMAP *map, const char *kstr, const char *vstr){ assert(map && kstr && vstr); tcmapput(map, kstr, strlen(kstr), vstr, strlen(vstr));}/* Store a record of the value of two regions into a map object. */void tcmapput3(TCMAP *map, const void *kbuf, int ksiz, const void *fvbuf, int fvsiz, const void *lvbuf, int lvsiz){ assert(map && kbuf && ksiz >= 0 && fvbuf && fvsiz >= 0 && lvbuf && lvsiz >= 0); unsigned int hash; TCMAPHASH1(hash, kbuf, ksiz); int bidx = hash % map->bnum; TCMAPREC *rec = map->buckets[bidx]; TCMAPREC **entp = map->buckets + bidx; TCMAPHASH2(hash, kbuf, ksiz); while(rec){ if(hash > rec->hash){ entp = &(rec->left); rec = rec->left; } else if(hash < rec->hash){ entp = &(rec->right); rec = rec->right; } else { char *dbuf = (char *)rec + sizeof(*rec); int kcmp = TCKEYCMP(kbuf, ksiz, dbuf, rec->ksiz); if(kcmp < 0){ entp = &(rec->left); rec = rec->left; } else if(kcmp > 0){ entp = &(rec->right); rec = rec->right; } else { int vsiz = fvsiz + lvsiz; map->msiz += vsiz - rec->vsiz; int psiz = TCALIGNPAD(ksiz); ksiz += psiz; if(vsiz > rec->vsiz){ TCMAPREC *old = rec; TCREALLOC(rec, rec, sizeof(*rec) + ksiz + 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; if(*entp == old) *entp = rec; if(rec->prev) rec->prev->next = rec; if(rec->next) rec->next->prev = rec; dbuf = (char *)rec + sizeof(*rec); } } memcpy(dbuf + ksiz, fvbuf, fvsiz); memcpy(dbuf + ksiz + fvsiz, lvbuf, lvsiz); dbuf[ksiz+vsiz] = '\0'; rec->vsiz = vsiz; return; } } } int vsiz = fvsiz + lvsiz; int psiz = TCALIGNPAD(ksiz); map->msiz += ksiz + vsiz; TCMALLOC(rec, sizeof(*rec) + ksiz + psiz + vsiz + 1); char *dbuf = (char *)rec + sizeof(*rec); memcpy(dbuf, kbuf, ksiz); dbuf[ksiz] = '\0'; rec->ksiz = ksiz; ksiz += psiz; memcpy(dbuf + ksiz, fvbuf, fvsiz); memcpy(dbuf + ksiz + fvsiz, lvbuf, lvsiz); dbuf[ksiz+vsiz] = '\0'; rec->vsiz = vsiz; rec->hash = hash; 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++;}/* Store a new record into a map object. */bool tcmapputkeep(TCMAP *map, const void *kbuf, int ksiz, const void *vbuf, int vsiz){ assert(map && kbuf && ksiz >= 0 && vbuf && vsiz >= 0); unsigned int hash; TCMAPHASH1(hash, kbuf, ksiz); int bidx = hash % map->bnum; TCMAPREC *rec = map->buckets[bidx]; TCMAPREC **entp = map->buckets + bidx; TCMAPHASH2(hash, kbuf, ksiz); while(rec){ if(hash > rec->hash){ entp = &(rec->left); rec = rec->left; } else if(hash < rec->hash){ entp = &(rec->right); rec = rec->right; } else { char *dbuf = (char *)rec + sizeof(*rec); int kcmp = TCKEYCMP(kbuf, ksiz, dbuf, rec->ksiz); if(kcmp < 0){ entp = &(rec->left); rec = rec->left; } else if(kcmp > 0){ entp = &(rec->right); rec = rec->right; } else { return false; } } } int psiz = TCALIGNPAD(ksiz); map->msiz += ksiz + vsiz; TCMALLOC(rec, sizeof(*rec) + ksiz + psiz + vsiz + 1); char *dbuf = (char *)rec + sizeof(*rec); memcpy(dbuf, kbuf, ksiz); dbuf[ksiz] = '\0'; rec->ksiz = ksiz; memcpy(dbuf + ksiz + psiz, vbuf, vsiz); dbuf[ksiz+psiz+vsiz] = '\0'; rec->vsiz = vsiz; rec->hash = hash; 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 true;}/* Store a new string record into a map object. */bool tcmapputkeep2(TCMAP *map, const char *kstr, const char *vstr){ assert(map && kstr && vstr); return tcmapputkeep(map, kstr, strlen(kstr), vstr, strlen(vstr));}/* Concatenate a value at the end of the value of the existing record in a map object. */void tcmapputcat(TCMAP *map, const void *kbuf, int ksiz, const void *vbuf, int vsiz){ assert(map && kbuf && ksiz >= 0 && vbuf && vsiz >= 0); unsigned int hash; TCMAPHASH1(hash, kbuf, ksiz); int bidx = hash % map->bnum; TCMAPREC *rec = map->buckets[bidx]; TCMAPREC **entp = map->buckets + bidx; TCMAPHASH2(hash, kbuf, ksiz); while(rec){ if(hash > rec->hash){ entp = &(rec->left); rec = rec->left; } else if(hash < rec->hash){ entp = &(rec->right); rec = rec->right; } else { char *dbuf = (char *)rec + sizeof(*rec); int kcmp = TCKEYCMP(kbuf, ksiz, dbuf, rec->ksiz); if(kcmp < 0){ entp = &(rec->left); rec = rec->left; } else if(kcmp > 0){ entp = &(rec->right); rec = rec->right; } else { map->msiz += vsiz; int psiz = TCALIGNPAD(ksiz); int asiz = sizeof(*rec) + ksiz + psiz + rec->vsiz + vsiz + 1; int unit = (asiz <= TCMAPCSUNIT) ? TCMAPCSUNIT : TCMAPCBUNIT; asiz = (asiz - 1) + unit - (asiz - 1) % unit; TCMAPREC *old = rec; TCREALLOC(rec, rec, asiz); if(rec != old){ if(map->first == old) map->first = rec; if(map->last == old) map->last = rec; if(map->cur == old) map->cur = rec; if(*entp == old) *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 + rec->vsiz, vbuf, vsiz); rec->vsiz += vsiz; dbuf[ksiz+psiz+rec->vsiz] = '\0'; return; } } } int psiz = TCALIGNPAD(ksiz); int asiz = sizeof(*rec) + ksiz + psiz + vsiz + 1; int unit = (asiz <= TCMAPCSUNIT) ? TCMAPCSUNIT : TCMAPCBUNIT; asiz = (asiz - 1) + unit - (asiz - 1) % unit; map->msiz += ksiz + vsiz; TCMALLOC(rec, asiz); char *dbuf = (char *)rec + sizeof(*rec); memcpy(dbuf, kbuf, ksiz); dbuf[ksiz] = '\0'; rec->ksiz = ksiz; memcpy(dbuf + ksiz + psiz, vbuf, vsiz); dbuf[ksiz+psiz+vsiz] = '\0'; rec->vsiz = vsiz; rec->hash = hash; 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++;}/* Concatenate a string value at the end of the value of the existing record in a map object. */void tcmapputcat2(TCMAP *map, const char *kstr, const char *vstr){ assert(map && kstr && vstr); tcmapputcat(map, kstr, strlen(kstr), vstr, strlen(vstr));}/* Remove a record of a map object. */bool tcmapout(TCMAP *map, const void *kbuf, int ksiz){ assert(map && kbuf && ksiz >= 0); unsigned int hash; TCMAPHASH1(hash, kbuf, ksiz); int bidx = hash % map->bnum; TCMAPREC *rec = map->buckets[bidx]; TCMAPREC **entp = map->buckets + bidx; TCMAPHASH2(hash, kbuf, ksiz); while(rec){ if(hash > rec->hash){ entp = &(rec->left); rec = rec->left; } else if(hash < rec->hash){ entp = &(rec->right); rec = rec->right; } else { char *dbuf = (char *)rec + sizeof(*rec); int kcmp = TCKEYCMP(kbuf, ksiz, dbuf, rec->ksiz); if(kcmp < 0){ entp = &(rec->left); rec = rec->left; } else if(kcmp > 0){ entp = &(rec->right); rec = rec->right; } else { map->rnum--; map->msiz -= rec->ksiz + rec->vsiz; if(rec->prev) rec->prev->next = rec->next; if(rec->next) rec->next->prev = rec->prev; if(rec == map->first) map->first = rec->next; if(rec == map->last) map->last = rec->prev; if(rec == map->cur) map->cur = rec->next; if(rec->left && !rec->right){ *entp = rec->left; } else if(!rec->left && rec->right){ *entp = rec->right; } else if(!rec->left && !rec->left){ *entp = NULL; } else { *entp = rec->left; TCMAPREC *tmp = *entp; while(tmp->right){ tmp = tmp->right; } tmp->right = rec->right; } TCFREE(rec); return true; } } } return false;}/* Remove a string record of a map object. */bool tcmapout2(TCMAP *map, const char *kstr){ assert(map && kstr); return tcmapout(map, kstr, strlen(kstr));}/* Retrieve a record in a map object. */const void *tcmapget(const TCMAP *map, const void *kbuf, int ksiz, int *sp){ assert(map && kbuf && ksiz >= 0 && sp); unsigned int hash; TCMAPHASH1(hash, kbuf, ksiz); TCMAPREC *rec = map->buckets[hash%map->bnum]; TCMAPHASH2(hash, kbuf, ksiz); while(rec){ if(hash > rec->hash){ rec = rec->left; } else if(hash < rec->hash){ rec = rec->right; } else { char *dbuf = (char *)rec + sizeof(*rec); int kcmp = TCKEYCMP(kbuf, ksiz, dbuf, rec->ksiz); if(kcmp < 0){ rec = rec->left; } else if(kcmp > 0){ rec = rec->right; } else { *sp = rec->vsiz; return dbuf + rec->ksiz + TCALIGNPAD(rec->ksiz); } } } 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); unsigned int hash; TCMAPHASH1(hash, kstr, ksiz); TCMAPREC *rec = map->buckets[hash%map->bnum]; TCMAPHASH2(hash, kstr, ksiz); while(rec){ if(hash > rec->hash){ rec = rec->left; } else if(hash < rec->hash){ rec = rec->right; } else { char *dbuf = (char *)rec + sizeof(*rec); int kcmp = TCKEYCMP(kstr, ksiz, dbuf, rec->ksiz); if(kcmp < 0){ rec = rec->left; } else if(kcmp > 0){ rec = rec->right; } else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -