📄 cabin.c
字号:
} buf[size] = '\0'; if(close(fd) == -1 || rv == -1){ free(buf); return NULL; } if(sp) *sp = size; return buf;}/* Read every line of a file. */CBLIST *cbreadlines(const char *name){ char *buf, *tmp; int vsiz; CBMAP *pairs; CBLIST *list; assert(name); if(!(buf = cbreadfile(name, NULL))) return NULL; pairs = cbmapopen(); 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(cblistnum(list) > 0){ cblistval(list, cblistnum(list) - 1, &vsiz); if(vsiz < 1) free(cblistpop(list, NULL)); } 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; list = cblistopen(); while((dp = readdir(DD)) != NULL){ cblistpush(list, dp->d_name, -1); } if(closedir(DD) == -1){ cblistclose(list); return NULL; } return list;}/* Get the status of a file or a directory. */int cbfilestat(const char *name, int *isdirp, int *sizep, int *mtimep){ struct stat sbuf; assert(name); if(stat(name, &sbuf) == -1) return FALSE; if(isdirp) *isdirp = S_ISDIR(sbuf.st_mode); if(sizep) *sizep = (int)sbuf.st_size; if(mtimep) *mtimep = (int)sbuf.st_mtime; return TRUE;}/* 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); buf = cbmalloc(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 if(c == ' '){ *(wp++) = '+'; } else { wp += sprintf(wp, "%%%02X", c); } } *wp = '\0'; return buf;}/* Decode a string encoded with URL encoding. */char *cburldecode(const char *str, int *sp){ const char *hex = "1234567890abcdefABCDEF"; char *buf, *wp; unsigned char c; buf = cbmemdup(str, -1); wp = buf; while(*str != '\0'){ if(*str == '%'){ str++; if(strchr(hex, *str) && strchr(hex, *(str + 1))){ 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); buf = cbmalloc(4 * (size + 2) / 3 + 1); obj = (const unsigned char *)ptr; wp = buf; for(i = 0; i < size; i += 3){ *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]; obj += 3; } if(i == size + 1){ *(wp - 1) = '='; } else if(i == size + 2){ *(wp - 1) = *(wp - 2) = '='; } *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 && sp); cnt = bpos = eqcnt = 0; len = strlen(str); wp = obj = cbmalloc(len + 1); 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; buf = wp = cbmalloc(size * 3 + 1); 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); buf = wp = cbmalloc(strlen(str) + 1); 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;}/* 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);}/* 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);}/************************************************************************************************* * private objects *************************************************************************************************//* Show error message on the standard error output and exit. `message' specifies an error message. */static void cbmyfatal(const char *message){ char buf[CB_MSGBUFSIZ]; assert(message); sprintf(buf, "fatal error: %s\n", message); write(2, buf, strlen(buf)); exit(1);}/* Handler to invoke the global garbage collector. */static void cbggchandler(void){ cbggckeeper(NULL, NULL);}/* Manage resouces of the global garbage collector. `ptr' specifies the pointer to add to the collection. If it is `NULL', all resouces are released. `func' specifies the pointer to the function to release the resouces. */static void cbggckeeper(void *ptr, void *func){ static void **parray = NULL; static void **farray = NULL; static int onum = 0; static int asiz = CB_GCUNIT; int i; if(!ptr){ for(i = onum - 1; i >= 0; i--){ ((void (*)(void *))farray[i])(parray[i]); } free(parray); free(farray); return; } if(!parray){ parray = cbmalloc(sizeof(int) * asiz); farray = cbmalloc(sizeof(int) * asiz); if(atexit(cbggchandler) != 0){ if(cbfatalfunc){ cbfatalfunc("gc failed"); } else { cbmyfatal("gc failed"); } } } if(onum >= asiz){ asiz *= 2; parray = cbrealloc(parray, sizeof(int) * asiz); farray = cbrealloc(farray, sizeof(int) * 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 { 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;}/* Get the first hash value. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the key. The return value is 31 bit hash value of the key. */static int cbfirsthash(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;}/* Get the second hash value. `kbuf' specifies the pointer to the region of a key. `ksiz' specifies the size of the key. The return value is 31 bit hash value of the key. */static int cbsecondhash(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;}/* 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);}/* Set a buffer for a variable length number. `buf' specifies the pointer to the buffer. `num' specifies the number. The return value is the size of valid region. */static int cbsetvnumbuf(char *buf, int num){ div_t d; int len; assert(buf && num >= 0); if(num == 0){ ((signed char *)buf)[0] = 0; return 1; } len = 0; while(num > 0){ d = div(num, 128); num = d.quot; ((signed char *)buf)[len] = d.rem; if(num > 0) ((signed char *)buf)[len] = -(((signed char *)buf)[len]) - 1; len++; } return len;}/* Read a variable length buffer. `buf' specifies the pointer to the buffer. `size' specifies the limit size to read. `sp' specifies the pointer to a variable to which the size of the read region assigned. The return value is the value of the buffer. */static int cbreadvnumbuf(const char *buf, int size, int *sp){ int i, num, base; assert(buf && size > 0 && sp); num = 0; base = 1; if(size < 2){ *sp = 1; return ((signed char *)buf)[0]; } for(i = 0; i < size; i++){ if(((signed char *)buf)[i] >= 0){ num += ((signed char *)buf)[i] * base; break; } num += base * (((signed char *)buf)[i] + 1) * -1; base *= 128; } *sp = i + 1; return num;}/* END OF FILE */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -