/* Split 's' with separator in 'sep'. An array * of sds strings is returned. *count will be set * by reference to the number of tokens returned. * * On out of memory, zero length string, zero length * separator, NULL is returned. * * Note that 'sep' is able to split a string using * a multi-character separator. For example * sdssplit("foo_-_bar","_-_"); will return two * elements "foo" and "bar". * * This version of the function is binary-safe but * requires length arguments. sdssplit() is just the * same function but for zero-terminated strings. */ sds *sdssplitlen(char *s, int len, char *sep, int seplen, int *count) { int elements = 0, slots = 5, start = 0, j; sds *tokens = malloc(sizeof(sds)*slots); #ifdef SDS_ABORT_ON_OOM if (tokens == NULL) sdsOomAbort(); #endif if (seplen < 1 || len < 0 || tokens == NULL) return NULL; for (j = 0; j < (len-(seplen-1)); j++) { /* make sure there is room for the next element and the final one */ if (slots < elements+2) { slots *= 2; sds *newtokens = realloc(tokens,sizeof(sds)*slots); if (newtokens == NULL) { #ifdef SDS_ABORT_ON_OOM sdsOomAbort(); #else goto cleanup; #endif } tokens = newtokens; } /* search the separator */ if ((seplen == 1 && *(s+j) == sep[0]) || (memcmp(s+j,sep,seplen) == 0)) { tokens[elements] = sdsnewlen(s+start,j-start); if (tokens[elements] == NULL) { #ifdef SDS_ABORT_ON_OOM sdsOomAbort(); #else goto cleanup; #endif } elements++; start = j+seplen; j = j+seplen-1; /* skip the separator */ } } /* Add the final element. We are sure there is room in the tokens array. */ tokens[elements] = sdsnewlen(s+start,len-start); if (tokens[elements] == NULL) { #ifdef SDS_ABORT_ON_OOM sdsOomAbort(); #else goto cleanup; #endif } elements++; *count = elements; return tokens; #ifndef SDS_ABORT_ON_OOM cleanup: { int i; for (i = 0; i < elements; i++) sdsfree(tokens[i]); free(tokens); return NULL; } #endif }
//试图把fmt格式的内容加入到s的后面 sds sdscatprintf(sds s,const char*fmt,...) { va_list ap; char *buf,*t; size_t buflen=32; while(1){ buf=malloc(buflen); if(buf==NULL) sdsOomAbort(); buf[buflen-2]='\0'; va_start(ap,fmt); vsnprintf(buf,buflen,fmt,ap); va_end(ap); if(buf[buflen-2]!='\0'){//如果被覆盖了,显然需要重新分配更大的buf free(buf); buflen*=2; continue; } break; } //首先通过buf作为中间存放fmt格式的内容 t=sdscat(s,buf); free(buf); return t; }
sds sdscatprintf(sds s, const char *fmt, ...) { va_list ap; char *buf, *t; size_t buflen = 32; va_start(ap, fmt); while(1) { buf = malloc(buflen); #ifdef SDS_ABORT_ON_OOM if (buf == NULL) sdsOomAbort(); #else if (buf == NULL) return NULL; #endif buf[buflen-2] = '\0'; vsnprintf(buf, buflen, fmt, ap); if (buf[buflen-2] != '\0') { free(buf); buflen *= 2; continue; } break; } va_end(ap); t = sdscat(s, buf); free(buf); return t; }
/** make a new string with length of initlen, copy *init to the new string if *init is not null * be careful if strlen(init) < initlen, such as * a = sdsnewlen("abc", 10); * a = sdscat(a, "abc"); * printf("%s", a) ====> "abc", because a[4] == '\0'!!! ***/ sds sdsnewlen(const void *init, size_t initlen) { struct sdshdr *sh; /** * allocate the memory * sizeof(struct sdshdr) -> sizeof of struct * initlen -> sizeof the string * 1 -> room for '\0' **/ sh = zmalloc(sizeof(struct sdshdr)+initlen+1); #ifdef SDS_ABORT_ON_OOM if (sh == NULL) sdsOomAbort(); #else if (sh == NULL) return NULL; #endif /** * update struct sh * setup sh->len and sh->free * change size_t(initlen) to long(sh->len), there may get problem */ sh->len = initlen; sh->free = 0; if (initlen) {/*initlen > 0 */ /* setup sh->buf */ if (init) memcpy(sh->buf, init, initlen); /* copy the content from init */ else memset(sh->buf,0,initlen); /* set all the elements of sh->buf to 0 */ } /* add '\0' at then end of sh->buf */ sh->buf[initlen] = '\0'; /** * return the new string * sds --> typedef of char* **/ return (char*)sh->buf; }
sds sdscatvprintf(sds s, const char *fmt, va_list ap) { va_list cpy; char *buf, *t; size_t buflen = 16; while(1) { buf = zmalloc(buflen); #ifdef SDS_ABORT_ON_OOM if (buf == NULL) sdsOomAbort(); #else if (buf == NULL) return NULL; #endif buf[buflen-2] = '\0'; va_copy(cpy,ap); vsnprintf(buf, buflen, fmt, cpy); if (buf[buflen-2] != '\0') { zfree(buf); buflen *= 2; continue; } break; } t = sdscat(s, buf); zfree(buf); return t; }
/** * concat some format characters after s, * the format likes the parameter of printf */ sds sdscatprintf(sds s, const char *fmt, ...) { /* ap : va_list */ va_list ap; char *buf, *t; /* start buf size */ size_t buflen = 32; /* look for a suffient buf size */ while(1) { buf = zmalloc(buflen); #ifdef SDS_ABORT_ON_OOM if (buf == NULL) sdsOomAbort(); #else if (buf == NULL) return NULL; #endif buf[buflen-2] = '\0'; /* print the format string to buf */ va_start(ap, fmt); vsnprintf(buf, buflen, fmt, ap); va_end(ap); /* if buf isn't bigger enough to hold the format string * keeping on looking*/ if (buf[buflen-2] != '\0') { zfree(buf); buflen *= 2; continue; } break; } /* concat the format string after s */ t = sdscat(s, buf); /* free the memory we allocated before */ zfree(buf); return t; }
/** * make room for addlen byte after s * @s : the original string * @addlen: the length we want to add **/ static sds sdsMakeRoomFor(sds s, size_t addlen) { /* @sh : point the the struct contains s * @newsh : points the new struct */ struct sdshdr *sh, *newsh; /* calculate the free space of sh */ size_t free = sdsavail(s); size_t len, newlen; /* if there are enough free space for addlen */ if (free >= addlen) return s; len = sdslen(s); sh = (void*) (s-(sizeof(struct sdshdr))); /** * allocate (len + addlen)*2 space * we want (len + addlen) * so we may not reallocate memory next time **/ newlen = (len+addlen)*2; /* realloc the memory */ newsh = zrealloc(sh, sizeof(struct sdshdr)+newlen+1); #ifdef SDS_ABORT_ON_OOM if (newsh == NULL) sdsOomAbort(); #else if (newsh == NULL) return NULL; #endif /** * update the struct , newsh->len doesn't change **/ newsh->free = newlen - len; return newsh->buf; }
sds sdsnewlen(const void*init,size_t initlen) { struct sdshdr *sh; sh=malloc(sizeof(*sh)+initlen+1); if(sh==NULL) sdsOomAbort(); sh->len=initlen; sh->free=0; if(initlen){ if(init)memcpy(sh->buf,init,initlen); else memset(sh->buf,0,initlen); } sh->buf[initlen]='\0'; return (char*)sh->buf; }
static sds sdsMakeRoomFor(sds s,size_t addlen) { struct sdshdr*sh,*newsh; size_t free=sdsavail(s); size_t len,newlen; if(free>=addlen) return s; len=sdslen(s); sh=(void*)(s-(sizeof(struct sdshdr))); newlen=(len+addlen)*2; newsh=realloc(sh,sizeof(struct sdshdr)+newlen+1); if(newsh==NULL) sdsOomAbort(); newsh->free=newlen-len; return newsh->buf; }
sds sdsnewlen(const void *init, size_t initlen) { struct sdshdr *sh; sh = malloc(sizeof(struct sdshdr)+initlen+1); #ifdef SDS_ABORT_ON_OOM if (sh == NULL) sdsOomAbort(); #else if (sh == NULL) return NULL; #endif sh->len = initlen; sh->free = 0; if (initlen) { if (init) memcpy(sh->buf, init, initlen); else memset(sh->buf,0,initlen); } sh->buf[initlen] = '\0'; return (char*)sh->buf; }
static sds sdsMakeRoomFor(sds s, size_t addlen) { struct sdshdr *sh, *newsh; size_t free = sdsavail(s); size_t len, newlen; if (free >= addlen) return s; len = sdslen(s); sh = (void*) (s-(sizeof(struct sdshdr))); newlen = (len+addlen)*2; newsh = zrealloc(sh, sizeof(struct sdshdr)+newlen+1); #ifdef SDS_ABORT_ON_OOM if (newsh == NULL) sdsOomAbort(); #else if (newsh == NULL) return NULL; #endif newsh->free = (int)(newlen - len); return newsh->buf; }
sds sdsMakeRoomFor(sds s, size_t addlen) { struct sdshdr *sh, *newsh; size_t free = sdsavail(s); size_t len, newlen; if (free >= addlen) return s; len = sdslen(s); sh = (void*) (s-(sizeof(struct sdshdr))); newlen = (len+addlen); if (newlen < SDS_MAX_PREALLOC) newlen *= 2; else newlen += SDS_MAX_PREALLOC; newsh = realloc(sh, sizeof(struct sdshdr)+newlen+1); #ifdef SDS_ABORT_ON_OOM if (newsh == NULL) sdsOomAbort(); #else if (newsh == NULL) return NULL; #endif newsh->free = newlen - len; return newsh->buf; }
/* Split 's' with separator in 'sep'. An array * of sds strings is returned. *count will be set * by reference to the number of tokens returned. * * On out of memory, zero length string, zero length * separator, NULL is returned. * * Note that 'sep' is able to split a string using * a multi-character separator. For example * sdssplit("foo_-_bar","_-_"); will return two * elements "foo" and "bar". * * This version of the function is binary-safe but * requires length arguments. sdssplit() is just the * same function but for zero-terminated strings. */ sds *sdssplitlen(char *s, int len, char *sep, int seplen, int *count) { /** * @elements : count of split string * @slots : count of split string we could have *at most*, used for allocating memory * @start : the start position of next split string * @j : the current index of s */ int elements = 0, slots = 5, start = 0, j; /** * @tokens : store the split string */ sds *tokens = zmalloc(sizeof(sds)*slots); #ifdef SDS_ABORT_ON_OOM if (tokens == NULL) sdsOomAbort(); #endif /* empty sep, empty s or can't out of memory */ if (seplen < 1 || len < 0 || tokens == NULL) return NULL; /* split the string */ for (j = 0; j < (len-(seplen-1)); j++) { /* make sure there is room for the next element and the final one */ if (slots < elements+2) { sds *newtokens; /* double slots */ slots *= 2; /* realloct new room */ newtokens = zrealloc(tokens,sizeof(sds)*slots); if (newtokens == NULL) { #ifdef SDS_ABORT_ON_OOM sdsOomAbort(); #else goto cleanup; #endif } tokens = newtokens; } /* search the separator */ if ((seplen == 1 && *(s+j) == sep[0]) || (memcmp(s+j,sep,seplen) == 0)) { /* make a new sdshdr to hold new string */ tokens[elements] = sdsnewlen(s+start,j-start); if (tokens[elements] == NULL) { #ifdef SDS_ABORT_ON_OOM sdsOomAbort(); #else goto cleanup; #endif } /* update elements, start and j */ elements++; start = j+seplen; j = j+seplen-1; /* skip the separator */ } } /* Add the final element. We are sure there is room in the tokens array. */ tokens[elements] = sdsnewlen(s+start,len-start); if (tokens[elements] == NULL) { #ifdef SDS_ABORT_ON_OOM sdsOomAbort(); #else goto cleanup; #endif } /* update info, and return */ elements++; *count = elements; return tokens; #ifndef SDS_ABORT_ON_OOM cleanup: /* cleanup */ { int i; for (i = 0; i < elements; i++) sdsfree(tokens[i]); zfree(tokens); return NULL; } #endif }