📄 tcutil.c
字号:
/************************************************************************************************* * The utility API of Tokyo Cabinet * Copyright (C) 2006-2008 Mikio Hirabayashi * This file is part of Tokyo Cabinet. * Tokyo Cabinet 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. Tokyo Cabinet 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 Tokyo * Cabinet; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, * Boston, MA 02111-1307 USA. *************************************************************************************************/#include "tcutil.h"#include "myconf.h"#include "md5.h"/************************************************************************************************* * basic utilities *************************************************************************************************//* String containing the version information. */const char *tcversion = _TC_VERSION;/* Call back function for handling a fatal error. */void (*tcfatalfunc)(const char *message) = NULL;/* Allocate a region on memory. */void *tcmalloc(size_t size){ assert(size > 0 && size < INT_MAX); char *p; TCMALLOC(p, size); return p;}/* Allocate a nullified region on memory. */void *tccalloc(size_t nmemb, size_t size){ assert(nmemb > 0 && size < INT_MAX && size > 0 && size < INT_MAX); char *p; TCCALLOC(p, nmemb, size); return p;}/* Re-allocate a region on memory. */void *tcrealloc(void *ptr, size_t size){ assert(size >= 0 && size < INT_MAX); char *p; TCREALLOC(p, ptr, size); return p;}/* Duplicate a region on memory. */void *tcmemdup(const void *ptr, size_t size){ assert(ptr && size >= 0); char *p; TCMALLOC(p, size + 1); memcpy(p, ptr, size); p[size] = '\0'; return p;}/* Duplicate a string on memory. */char *tcstrdup(const void *str){ assert(str); int size = strlen(str); char *p; TCMALLOC(p, size + 1); memcpy(p, str, size); p[size] = '\0'; return p;}/* Free a region on memory. */void tcfree(void *ptr){ TCFREE(ptr);}/************************************************************************************************* * extensible string *************************************************************************************************/#define TCXSTRUNIT 12 // allocation unit size of an extensible string/* private function prototypes */static void tcvxstrprintf(TCXSTR *xstr, const char *format, va_list ap);/* Create an extensible string object. */TCXSTR *tcxstrnew(void){ TCXSTR *xstr; TCMALLOC(xstr, sizeof(*xstr)); TCMALLOC(xstr->ptr, TCXSTRUNIT); xstr->size = 0; xstr->asize = TCXSTRUNIT; xstr->ptr[0] = '\0'; return xstr;}/* Create an extensible string object from a character string. */TCXSTR *tcxstrnew2(const char *str){ assert(str); TCXSTR *xstr; TCMALLOC(xstr, sizeof(*xstr)); int size = strlen(str); int asize = tclmax(size + 1, TCXSTRUNIT); TCMALLOC(xstr->ptr, asize); xstr->size = size; xstr->asize = asize; memcpy(xstr->ptr, str, size + 1); return xstr;}/* Create an extensible string object with the initial allocation size. */TCXSTR *tcxstrnew3(int asiz){ assert(asiz >= 0); asiz = tclmax(asiz, TCXSTRUNIT); TCXSTR *xstr; TCMALLOC(xstr, sizeof(*xstr)); TCMALLOC(xstr->ptr, asiz); xstr->size = 0; xstr->asize = asiz; xstr->ptr[0] = '\0'; return xstr;}/* Copy an extensible string object. */TCXSTR *tcxstrdup(const TCXSTR *xstr){ assert(xstr); TCXSTR *nxstr; TCMALLOC(nxstr, sizeof(*nxstr)); int asize = tclmax(xstr->size + 1, TCXSTRUNIT); TCMALLOC(nxstr->ptr, asize); nxstr->size = xstr->size; nxstr->asize = asize; memcpy(nxstr->ptr, xstr->ptr, xstr->size + 1); return nxstr;}/* Delete an extensible string object. */void tcxstrdel(TCXSTR *xstr){ assert(xstr); TCFREE(xstr->ptr); TCFREE(xstr);}/* Concatenate a region to the end of an extensible string object. */void tcxstrcat(TCXSTR *xstr, const void *ptr, int size){ assert(xstr && ptr && size >= 0); int nsize = xstr->size + size + 1; if(xstr->asize < nsize){ while(xstr->asize < nsize){ xstr->asize *= 2; if(xstr->asize < nsize) xstr->asize = nsize; } TCREALLOC(xstr->ptr, xstr->ptr, xstr->asize); } memcpy(xstr->ptr + xstr->size, ptr, size); xstr->size += size; xstr->ptr[xstr->size] = '\0';}/* Concatenate a character string to the end of an extensible string object. */void tcxstrcat2(TCXSTR *xstr, const char *str){ assert(xstr && str); int size = strlen(str); int nsize = xstr->size + size + 1; if(xstr->asize < nsize){ while(xstr->asize < nsize){ xstr->asize *= 2; if(xstr->asize < nsize) xstr->asize = nsize; } TCREALLOC(xstr->ptr, xstr->ptr, xstr->asize); } memcpy(xstr->ptr + xstr->size, str, size + 1); xstr->size += size;}/* Get the pointer of the region of an extensible string object. */const void *tcxstrptr(const TCXSTR *xstr){ assert(xstr); return xstr->ptr;}/* Get the size of the region of an extensible string object. */int tcxstrsize(const TCXSTR *xstr){ assert(xstr); return xstr->size;}/* Clear an extensible string object. */void tcxstrclear(TCXSTR *xstr){ assert(xstr); xstr->size = 0; xstr->ptr[0] = '\0';}/* Convert an extensible string object into a usual allocated region. */void *tcxstrtomalloc(TCXSTR *xstr){ assert(xstr); char *ptr; ptr = xstr->ptr; TCFREE(xstr); return ptr;}/* Create an extensible string object from an allocated region. */TCXSTR *tcxstrfrommalloc(void *ptr, int size){ TCXSTR *xstr; TCMALLOC(xstr, sizeof(*xstr)); TCREALLOC(xstr->ptr, ptr, size + 1); xstr->ptr[size] = '\0'; xstr->size = size; xstr->asize = size; return xstr;}/* Perform formatted output into an extensible string object. */void tcxstrprintf(TCXSTR *xstr, const char *format, ...){ assert(xstr && format); va_list ap; va_start(ap, format); tcvxstrprintf(xstr, format, ap); va_end(ap);}/* Allocate a formatted string on memory. */char *tcsprintf(const char *format, ...){ assert(format); TCXSTR *xstr = tcxstrnew(); va_list ap; va_start(ap, format); tcvxstrprintf(xstr, format, ap); va_end(ap); return tcxstrtomalloc(xstr);}/* Perform formatted output into an extensible string object. */static void tcvxstrprintf(TCXSTR *xstr, const char *format, va_list ap){ assert(xstr && format); while(*format != '\0'){ if(*format == '%'){ char cbuf[TCNUMBUFSIZ]; cbuf[0] = '%'; int cblen = 1; int lnum = 0; format++; while(strchr("0123456789 .+-hlLz", *format) && *format != '\0' && cblen < TCNUMBUFSIZ - 1){ if(*format == 'l' || *format == 'L') lnum++; cbuf[cblen++] = *(format++); } cbuf[cblen++] = *format; cbuf[cblen] = '\0'; int tlen; char *tmp, tbuf[TCNUMBUFSIZ*4]; switch(*format){ case 's': tmp = va_arg(ap, char *); if(!tmp) tmp = "(null)"; tcxstrcat2(xstr, tmp); break; case 'd': if(lnum >= 2){ tlen = sprintf(tbuf, cbuf, va_arg(ap, long long)); } else if(lnum >= 1){ tlen = sprintf(tbuf, cbuf, va_arg(ap, long)); } else { tlen = sprintf(tbuf, cbuf, va_arg(ap, int)); } TCXSTRCAT(xstr, tbuf, tlen); break; case 'o': case 'u': case 'x': case 'X': case 'c': if(lnum >= 2){ tlen = sprintf(tbuf, cbuf, va_arg(ap, unsigned long long)); } else if(lnum >= 1){ tlen = sprintf(tbuf, cbuf, va_arg(ap, unsigned long)); } else { tlen = sprintf(tbuf, cbuf, va_arg(ap, unsigned int)); } TCXSTRCAT(xstr, tbuf, tlen); break; case 'e': case 'E': case 'f': case 'g': case 'G': if(lnum >= 1){ tlen = snprintf(tbuf, sizeof(tbuf), cbuf, va_arg(ap, long double)); } else { tlen = snprintf(tbuf, sizeof(tbuf), cbuf, va_arg(ap, double)); } if(tlen < 0 || tlen > sizeof(tbuf)){ tbuf[sizeof(tbuf)-1] = '*'; tlen = sizeof(tbuf); } TCXSTRCAT(xstr, tbuf, tlen); break; case '@': tmp = va_arg(ap, char *); if(!tmp) tmp = "(null)"; while(*tmp){ switch(*tmp){ case '&': TCXSTRCAT(xstr, "&", 5); break; case '<': TCXSTRCAT(xstr, "<", 4); break; case '>': TCXSTRCAT(xstr, ">", 4); break; case '"': TCXSTRCAT(xstr, """, 6); break; default: if(!((*tmp >= 0 && *tmp <= 0x8) || (*tmp >= 0x0e && *tmp <= 0x1f))) TCXSTRCAT(xstr, tmp, 1); break; } tmp++; } break; case '?': tmp = va_arg(ap, char *); if(!tmp) tmp = "(null)"; while(*tmp){ unsigned char c = *(unsigned char *)tmp; if((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || (c != '\0' && strchr("_-.", c))){ TCXSTRCAT(xstr, tmp, 1); } else { tlen = sprintf(tbuf, "%%%02X", c); TCXSTRCAT(xstr, tbuf, tlen); } tmp++; } break; case 'b': if(lnum >= 2){ tlen = tcnumtostrbin(va_arg(ap, unsigned long long), tbuf, atoi(cbuf + 1), cbuf[1] == '0' ? '0' : ' '); } else if(lnum >= 1){ tlen = tcnumtostrbin(va_arg(ap, unsigned long), tbuf, atoi(cbuf + 1), cbuf[1] == '0' ? '0' : ' '); } else { tlen = tcnumtostrbin(va_arg(ap, unsigned int), tbuf, atoi(cbuf + 1), cbuf[1] == '0' ? '0' : ' '); } TCXSTRCAT(xstr, tbuf, tlen); break; case '%': TCXSTRCAT(xstr, "%", 1); break; } } else { TCXSTRCAT(xstr, format, 1); } format++; }}/************************************************************************************************* * array list *************************************************************************************************/#define TCLISTUNIT 64 // allocation unit number of a list handle/* private function prototypes */static int tclistelemcmp(const void *a, const void *b);static int tclistelemcmpci(const void *a, const void *b);/* Create a list object. */TCLIST *tclistnew(void){ TCLIST *list; TCMALLOC(list, sizeof(*list)); list->anum = TCLISTUNIT; TCMALLOC(list->array, sizeof(list->array[0]) * list->anum); list->start = 0; list->num = 0; return list;}/* Create a list object. */TCLIST *tclistnew2(int anum){ TCLIST *list; TCMALLOC(list, sizeof(*list)); if(anum < 1) anum = 1; list->anum = anum; TCMALLOC(list->array, sizeof(list->array[0]) * list->anum); list->start = 0; list->num = 0; return list;}/* Copy a list object. */TCLIST *tclistdup(const TCLIST *list){ assert(list); int num = list->num; if(num < 1) return tclistnew(); const TCLISTDATUM *array = list->array + list->start; TCLIST *nlist; TCMALLOC(nlist, sizeof(*nlist)); TCLISTDATUM *narray; TCMALLOC(narray, sizeof(list->array[0]) * num); for(int i = 0; i < num; i++){ int size = array[i].size; TCMALLOC(narray[i].ptr, tclmax(size + 1, TCXSTRUNIT)); memcpy(narray[i].ptr, array[i].ptr, size + 1); narray[i].size = array[i].size; } nlist->anum = num; nlist->array = narray; nlist->start = 0; nlist->num = num; return nlist;}/* Delete a list object. */void tclistdel(TCLIST *list){ assert(list); TCLISTDATUM *array = list->array; int end = list->start + list->num; for(int i = list->start; i < end; i++){ TCFREE(array[i].ptr); } TCFREE(list->array); TCFREE(list);}/* Get the number of elements of a list object. */int tclistnum(const TCLIST *list){ assert(list); return list->num;}/* Get the pointer to the region of an element of a list object. */const void *tclistval(const TCLIST *list, int index, int *sp){ assert(list && index >= 0 && sp);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -