diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/sds.c | 808 | ||||
-rw-r--r-- | src/sds.h | 16 |
2 files changed, 411 insertions, 413 deletions
@@ -46,43 +46,43 @@ * end of the string. However the string is binary safe and can contain * \0 characters in the middle, as the length is stored in the sds header. */ sds sdsnewlen(const void *init, size_t initlen) { - struct sdshdr *sh; - - if (init) { - sh = malloc(sizeof(struct sdshdr)+initlen+1); - } else { - sh = calloc(sizeof(struct sdshdr)+initlen+1,1); - } - if (sh == NULL) return NULL; - sh->len = initlen; - sh->free = 0; - if (initlen && init) - memcpy(sh->buf, init, initlen); - sh->buf[initlen] = '\0'; - return (char*)sh->buf; + struct sdshdr *sh; + + if (init) { + sh = malloc(sizeof(struct sdshdr)+initlen+1); + } else { + sh = calloc(sizeof(struct sdshdr)+initlen+1,1); + } + if (sh == NULL) return NULL; + sh->len = initlen; + sh->free = 0; + if (initlen && init) + memcpy(sh->buf, init, initlen); + sh->buf[initlen] = '\0'; + return (char*)sh->buf; } /* Create an empty (zero length) sds string. Even in this case the string * always has an implicit null term. */ sds sdsempty(void) { - return sdsnewlen("",0); + return sdsnewlen("",0); } /* Create a new sds string starting from a null termined C string. */ sds sdsnew(const char *init) { - size_t initlen = (init == NULL) ? 0 : strlen(init); - return sdsnewlen(init, initlen); + size_t initlen = (init == NULL) ? 0 : strlen(init); + return sdsnewlen(init, initlen); } /* Duplicate an sds string. */ sds sdsdup(const sds s) { - return sdsnewlen(s, sdslen(s)); + return sdsnewlen(s, sdslen(s)); } /* Free an sds string. No operation is performed if 's' is NULL. */ void sdsfree(sds s) { - if (s == NULL) return; - free(sdsheader(s)); + if (s == NULL) return; + free(sdsheader(s)); } /* Set the sds string length to the length as obtained with strlen(), so @@ -100,10 +100,10 @@ void sdsfree(sds s) { * the output will be "6" as the string was modified but the logical length * remains 6 bytes. */ void sdsupdatelen(sds s) { - struct sdshdr *sh = sdsheader(s); - int reallen = strlen(s); - sh->free += (sh->len-reallen); - sh->len = reallen; + struct sdshdr *sh = sdsheader(s); + int reallen = strlen(s); + sh->free += (sh->len-reallen); + sh->len = reallen; } /* Modify an sds string on-place to make it empty (zero length). @@ -111,10 +111,10 @@ void sdsupdatelen(sds s) { * so that next append operations will not require allocations up to the * number of bytes previously available. */ void sdsclear(sds s) { - struct sdshdr *sh = sdsheader(s); - sh->free += sh->len; - sh->len = 0; - sh->buf[0] = '\0'; + struct sdshdr *sh = sdsheader(s); + sh->free += sh->len; + sh->len = 0; + sh->buf[0] = '\0'; } /* Enlarge the free space at the end of the sds string so that the caller @@ -124,23 +124,23 @@ void sdsclear(sds s) { * Note: this does not change the *length* of the sds string as returned * by sdslen(), but only the free buffer space we have. */ sds sdsMakeRoomFor(sds s, size_t addlen) { - struct sdshdr *sh, *newsh; - size_t free = sdsavail(s); - size_t len, newlen; + struct sdshdr *sh, *newsh; + size_t free = sdsavail(s); + size_t len, newlen; - if (free >= addlen) return s; - len = sdslen(s); - sh = sdsheader(s); - newlen = (len+addlen); - if (newlen < SDS_MAX_PREALLOC) - newlen *= 2; - else - newlen += SDS_MAX_PREALLOC; - newsh = realloc(sh, sizeof(struct sdshdr)+newlen+1); - if (newsh == NULL) return NULL; + if (free >= addlen) return s; + len = sdslen(s); + sh = sdsheader(s); + newlen = (len+addlen); + if (newlen < SDS_MAX_PREALLOC) + newlen *= 2; + else + newlen += SDS_MAX_PREALLOC; + newsh = realloc(sh, sizeof(struct sdshdr)+newlen+1); + if (newsh == NULL) return NULL; - newsh->free = newlen - len; - return newsh->buf; + newsh->free = newlen - len; + return newsh->buf; } /* Reallocate the sds string so that it has no free space at the end. The @@ -150,12 +150,12 @@ sds sdsMakeRoomFor(sds s, size_t addlen) { * After the call, the passed sds string is no longer valid and all the * references must be substituted with the new pointer returned by the call. */ sds sdsRemoveFreeSpace(sds s) { - struct sdshdr *sh; + struct sdshdr *sh; - sh = sdsheader(s); - sh = realloc(sh, sizeof(struct sdshdr)+sh->len+1); - sh->free = 0; - return sh->buf; + sh = sdsheader(s); + sh = realloc(sh, sizeof(struct sdshdr)+sh->len+1); + sh->free = 0; + return sh->buf; } /* Return the total size of the allocation of the specifed sds string, @@ -166,9 +166,9 @@ sds sdsRemoveFreeSpace(sds s) { * 4) The implicit null term. */ size_t sdsAllocSize(sds s) { - struct sdshdr *sh = sdsheader(s); + struct sdshdr *sh = sdsheader(s); - return sizeof(*sh)+sh->len+sh->free+1; + return sizeof(*sh)+sh->len+sh->free+1; } /* Increment the sds length and decrements the left free space at the @@ -195,13 +195,13 @@ size_t sdsAllocSize(sds s) { * sdsIncrLen(s, nread); */ void sdsIncrLen(sds s, int incr) { - struct sdshdr *sh = sdsheader(s); + struct sdshdr *sh = sdsheader(s); - assert(sh->free >= incr); - sh->len += incr; - sh->free -= incr; - assert(sh->free >= 0); - s[sh->len] = '\0'; + assert(sh->free >= incr); + sh->len += incr; + sh->free -= incr; + assert(sh->free >= 0); + s[sh->len] = '\0'; } /* Grow the sds to have the specified length. Bytes that were not part of @@ -210,20 +210,20 @@ void sdsIncrLen(sds s, int incr) { * if the specified length is smaller than the current length, no operation * is performed. */ sds sdsgrowzero(sds s, size_t len) { - struct sdshdr *sh = sdsheader(s); - size_t totlen, curlen = sh->len; + struct sdshdr *sh = sdsheader(s); + size_t totlen, curlen = sh->len; - if (len <= curlen) return s; - s = sdsMakeRoomFor(s,len-curlen); - if (s == NULL) return NULL; + if (len <= curlen) return s; + s = sdsMakeRoomFor(s,len-curlen); + if (s == NULL) return NULL; - /* Make sure added region doesn't contain garbage */ - sh = sdsheader(s); - memset(s+curlen,0,(len-curlen+1)); /* also set trailing \0 byte */ - totlen = sh->len+sh->free; - sh->len = len; - sh->free = totlen-sh->len; - return s; + /* Make sure added region doesn't contain garbage */ + sh = sdsheader(s); + memset(s+curlen,0,(len-curlen+1)); /* also set trailing \0 byte */ + totlen = sh->len+sh->free; + sh->len = len; + sh->free = totlen-sh->len; + return s; } /* Append the specified binary-safe string pointed by 't' of 'len' bytes to the @@ -232,17 +232,17 @@ sds sdsgrowzero(sds s, size_t len) { * After the call, the passed sds string is no longer valid and all the * references must be substituted with the new pointer returned by the call. */ sds sdscatlen(sds s, const void *t, size_t len) { - struct sdshdr *sh; - size_t curlen = sdslen(s); + struct sdshdr *sh; + size_t curlen = sdslen(s); - s = sdsMakeRoomFor(s,len); - if (s == NULL) return NULL; - sh = sdsheader(s); - memcpy(s+curlen, t, len); - sh->len = curlen+len; - sh->free = sh->free-len; - s[curlen+len] = '\0'; - return s; + s = sdsMakeRoomFor(s,len); + if (s == NULL) return NULL; + sh = sdsheader(s); + memcpy(s+curlen, t, len); + sh->len = curlen+len; + sh->free = sh->free-len; + s[curlen+len] = '\0'; + return s; } /* Append the specified null termianted C string to the sds string 's'. @@ -250,7 +250,7 @@ sds sdscatlen(sds s, const void *t, size_t len) { * After the call, the passed sds string is no longer valid and all the * references must be substituted with the new pointer returned by the call. */ sds sdscat(sds s, const char *t) { - return sdscatlen(s, t, strlen(t)); + return sdscatlen(s, t, strlen(t)); } /* Append the specified sds 't' to the existing sds 's'. @@ -258,56 +258,56 @@ sds sdscat(sds s, const char *t) { * After the call, the modified sds string is no longer valid and all the * references must be substituted with the new pointer returned by the call. */ sds sdscatsds(sds s, const sds t) { - return sdscatlen(s, t, sdslen(t)); + return sdscatlen(s, t, sdslen(t)); } /* Destructively modify the sds string 's' to hold the specified binary * safe string pointed by 't' of length 'len' bytes. */ sds sdscpylen(sds s, const char *t, size_t len) { - struct sdshdr *sh = sdsheader(s); - size_t totlen = sh->free+sh->len; - - if (totlen < len) { - s = sdsMakeRoomFor(s,len-sh->len); - if (s == NULL) return NULL; - sh = sdsheader(s); - totlen = sh->free+sh->len; - } - memcpy(s, t, len); - s[len] = '\0'; - sh->len = len; - sh->free = totlen-len; - return s; + struct sdshdr *sh = sdsheader(s); + size_t totlen = sh->free+sh->len; + + if (totlen < len) { + s = sdsMakeRoomFor(s,len-sh->len); + if (s == NULL) return NULL; + sh = sdsheader(s); + totlen = sh->free+sh->len; + } + memcpy(s, t, len); + s[len] = '\0'; + sh->len = len; + sh->free = totlen-len; + return s; } /* Like sdscpylen() but 't' must be a null-termined string so that the length * of the string is obtained with strlen(). */ sds sdscpy(sds s, const char *t) { - return sdscpylen(s, t, strlen(t)); + return sdscpylen(s, t, strlen(t)); } /* Like sdscatpritf() but gets va_list instead of being variadic. */ sds sdscatvprintf(sds s, const char *fmt, va_list ap) { - va_list cpy; - char *buf, *t; - size_t buflen = 16; - - while(1) { - buf = malloc(buflen); - if (buf == NULL) return NULL; - buf[buflen-2] = '\0'; - va_copy(cpy,ap); - vsnprintf(buf, buflen, fmt, cpy); - if (buf[buflen-2] != '\0') { - free(buf); - buflen *= 2; - continue; - } - break; - } - t = sdscat(s, buf); - free(buf); - return t; + va_list cpy; + char *buf, *t; + size_t buflen = 16; + + while(1) { + buf = malloc(buflen); + if (buf == NULL) return NULL; + buf[buflen-2] = '\0'; + va_copy(cpy,ap); + vsnprintf(buf, buflen, fmt, cpy); + if (buf[buflen-2] != '\0') { + free(buf); + buflen *= 2; + continue; + } + break; + } + t = sdscat(s, buf); + free(buf); + return t; } /* Append to the sds string 's' a string obtained using printf-alike format @@ -327,12 +327,12 @@ sds sdscatvprintf(sds s, const char *fmt, va_list ap) { * s = sdscatprintf(sdsempty(), "... your format ...", args); */ sds sdscatprintf(sds s, const char *fmt, ...) { - va_list ap; - char *t; - va_start(ap, fmt); - t = sdscatvprintf(s,fmt,ap); - va_end(ap); - return t; + va_list ap; + char *t; + va_start(ap, fmt); + t = sdscatvprintf(s,fmt,ap); + va_end(ap); + return t; } /* Remove the part of the string from left and from right composed just of @@ -350,19 +350,19 @@ sds sdscatprintf(sds s, const char *fmt, ...) { * Output will be just "Hello World". */ void sdstrim(sds s, const char *cset) { - struct sdshdr *sh = sdsheader(s); - char *start, *end, *sp, *ep; - size_t len; + struct sdshdr *sh = sdsheader(s); + char *start, *end, *sp, *ep; + size_t len; - sp = start = s; - ep = end = s+sdslen(s)-1; - while(sp <= end && strchr(cset, *sp)) sp++; - while(ep > start && strchr(cset, *ep)) ep--; - len = (sp > ep) ? 0 : ((ep-sp)+1); - if (sh->buf != sp) memmove(sh->buf, sp, len); - sh->buf[len] = '\0'; - sh->free = sh->free+(sh->len-len); - sh->len = len; + sp = start = s; + ep = end = s+sdslen(s)-1; + while(sp <= end && strchr(cset, *sp)) sp++; + while(ep > start && strchr(cset, *ep)) ep--; + len = (sp > ep) ? 0 : ((ep-sp)+1); + if (sh->buf != sp) memmove(sh->buf, sp, len); + sh->buf[len] = '\0'; + sh->free = sh->free+(sh->len-len); + sh->len = len; } /* Turn the string into a smaller (or equal) string containing only the @@ -382,47 +382,47 @@ void sdstrim(sds s, const char *cset) { * sdsrange(s,1,-1); => "ello World" */ void sdsrange(sds s, int start, int end) { - struct sdshdr *sh = sdsheader(s); - size_t newlen, len = sdslen(s); - - if (len == 0) return; - if (start < 0) { - start = len+start; - if (start < 0) start = 0; - } - if (end < 0) { - end = len+end; - if (end < 0) end = 0; - } - newlen = (start > end) ? 0 : (end-start)+1; - if (newlen != 0) { - if (start >= (signed)len) { - newlen = 0; - } else if (end >= (signed)len) { - end = len-1; - newlen = (start > end) ? 0 : (end-start)+1; - } - } else { - start = 0; - } - if (start && newlen) memmove(sh->buf, sh->buf+start, newlen); - sh->buf[newlen] = 0; - sh->free = sh->free+(sh->len-newlen); - sh->len = newlen; + struct sdshdr *sh = sdsheader(s); + size_t newlen, len = sdslen(s); + + if (len == 0) return; + if (start < 0) { + start = len+start; + if (start < 0) start = 0; + } + if (end < 0) { + end = len+end; + if (end < 0) end = 0; + } + newlen = (start > end) ? 0 : (end-start)+1; + if (newlen != 0) { + if (start >= (signed)len) { + newlen = 0; + } else if (end >= (signed)len) { + end = len-1; + newlen = (start > end) ? 0 : (end-start)+1; + } + } else { + start = 0; + } + if (start && newlen) memmove(sh->buf, sh->buf+start, newlen); + sh->buf[newlen] = 0; + sh->free = sh->free+(sh->len-newlen); + sh->len = newlen; } /* Apply tolower() to every character of the sds string 's'. */ void sdstolower(sds s) { - int len = sdslen(s), j; + int len = sdslen(s), j; - for (j = 0; j < len; j++) s[j] = tolower(s[j]); + for (j = 0; j < len; j++) s[j] = tolower(s[j]); } /* Apply toupper() to every character of the sds string 's'. */ void sdstoupper(sds s) { - int len = sdslen(s), j; + int len = sdslen(s), j; - for (j = 0; j < len; j++) s[j] = toupper(s[j]); + for (j = 0; j < len; j++) s[j] = toupper(s[j]); } /* Compare two sds strings s1 and s2 with memcmp(). @@ -437,15 +437,15 @@ void sdstoupper(sds s) { * additional characters, the longer string is considered to be greater than * the smaller one. */ int sdscmp(const sds s1, const sds s2) { - size_t l1, l2, minlen; - int cmp; + size_t l1, l2, minlen; + int cmp; - l1 = sdslen(s1); - l2 = sdslen(s2); - minlen = (l1 < l2) ? l1 : l2; - cmp = memcmp(s1,s2,minlen); - if (cmp == 0) return l1-l2; - return cmp; + l1 = sdslen(s1); + l2 = sdslen(s2); + minlen = (l1 < l2) ? l1 : l2; + cmp = memcmp(s1,s2,minlen); + if (cmp == 0) return l1-l2; + return cmp; } /* Split 's' with separator in 'sep'. An array @@ -465,60 +465,60 @@ int sdscmp(const sds s1, const sds s2) { * same function but for zero-terminated strings. */ sds *sdssplitlen(const char *s, int len, const char *sep, int seplen, int *count) { - int elements = 0, slots = 5, start = 0, j; - sds *tokens; - - if (seplen < 1 || len < 0) return NULL; - - tokens = malloc(sizeof(sds)*slots); - if (tokens == NULL) return NULL; - - if (len == 0) { - *count = 0; - return tokens; - } - 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; - - slots *= 2; - newtokens = realloc(tokens,sizeof(sds)*slots); - if (newtokens == NULL) goto cleanup; - 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) goto cleanup; - 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) goto cleanup; - elements++; - *count = elements; - return tokens; + int elements = 0, slots = 5, start = 0, j; + sds *tokens; + + if (seplen < 1 || len < 0) return NULL; + + tokens = malloc(sizeof(sds)*slots); + if (tokens == NULL) return NULL; + + if (len == 0) { + *count = 0; + return tokens; + } + 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; + + slots *= 2; + newtokens = realloc(tokens,sizeof(sds)*slots); + if (newtokens == NULL) goto cleanup; + 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) goto cleanup; + 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) goto cleanup; + elements++; + *count = elements; + return tokens; cleanup: - { - int i; - for (i = 0; i < elements; i++) sdsfree(tokens[i]); - free(tokens); - *count = 0; - return NULL; - } + { + int i; + for (i = 0; i < elements; i++) sdsfree(tokens[i]); + free(tokens); + *count = 0; + return NULL; + } } /* Free the result returned by sdssplitlen(), or do nothing if 'tokens' is NULL. */ void sdsfreesplitres(sds *tokens, int count) { - if (!tokens) return; - while(count--) - sdsfree(tokens[count]); - free(tokens); + if (!tokens) return; + while(count--) + sdsfree(tokens[count]); + free(tokens); } /* Create an sds string from a long long value. It is much faster than: @@ -526,18 +526,18 @@ void sdsfreesplitres(sds *tokens, int count) { * sdscatprintf(sdsempty(),"%lld\n", value); */ sds sdsfromlonglong(long long value) { - char buf[32], *p; - unsigned long long v; + char buf[32], *p; + unsigned long long v; - v = (value < 0) ? -value : value; - p = buf+31; /* point to the last character */ - do { - *p-- = '0'+(v%10); - v /= 10; - } while(v); - if (value < 0) *p-- = '-'; - p++; - return sdsnewlen(p,32-(p-buf)); + v = (value < 0) ? -value : value; + p = buf+31; /* point to the last character */ + do { + *p-- = '0'+(v%10); + v /= 10; + } while(v); + if (value < 0) *p-- = '-'; + p++; + return sdsnewlen(p,32-(p-buf)); } /* Append to the sds string "s" an escaped string representation where @@ -547,59 +547,59 @@ sds sdsfromlonglong(long long value) { * After the call, the modified sds string is no longer valid and all the * references must be substituted with the new pointer returned by the call. */ sds sdscatrepr(sds s, const char *p, size_t len) { - s = sdscatlen(s,"\"",1); - while(len--) { - switch(*p) { - case '\\': - case '"': - s = sdscatprintf(s,"\\%c",*p); - break; - case '\n': s = sdscatlen(s,"\\n",2); break; - case '\r': s = sdscatlen(s,"\\r",2); break; - case '\t': s = sdscatlen(s,"\\t",2); break; - case '\a': s = sdscatlen(s,"\\a",2); break; - case '\b': s = sdscatlen(s,"\\b",2); break; - default: - if (isprint(*p)) - s = sdscatprintf(s,"%c",*p); - else - s = sdscatprintf(s,"\\x%02x",(unsigned char)*p); - break; - } - p++; - } - return sdscatlen(s,"\"",1); + s = sdscatlen(s,"\"",1); + while(len--) { + switch(*p) { + case '\\': + case '"': + s = sdscatprintf(s,"\\%c",*p); + break; + case '\n': s = sdscatlen(s,"\\n",2); break; + case '\r': s = sdscatlen(s,"\\r",2); break; + case '\t': s = sdscatlen(s,"\\t",2); break; + case '\a': s = sdscatlen(s,"\\a",2); break; + case '\b': s = sdscatlen(s,"\\b",2); break; + default: + if (isprint(*p)) + s = sdscatprintf(s,"%c",*p); + else + s = sdscatprintf(s,"\\x%02x",(unsigned char)*p); + break; + } + p++; + } + return sdscatlen(s,"\"",1); } /* Helper function for sdssplitargs() that returns non zero if 'c' * is a valid hex digit. */ int is_hex_digit(char c) { - return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || - (c >= 'A' && c <= 'F'); + return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || + (c >= 'A' && c <= 'F'); } /* Helper function for sdssplitargs() that converts a hex digit into an * integer from 0 to 15 */ int hex_digit_to_int(char c) { - switch(c) { - case '0': return 0; - case '1': return 1; - case '2': return 2; - case '3': return 3; - case '4': return 4; - case '5': return 5; - case '6': return 6; - case '7': return 7; - case '8': return 8; - case '9': return 9; - case 'a': case 'A': return 10; - case 'b': case 'B': return 11; - case 'c': case 'C': return 12; - case 'd': case 'D': return 13; - case 'e': case 'E': return 14; - case 'f': case 'F': return 15; - default: return 0; - } + switch(c) { + case '0': return 0; + case '1': return 1; + case '2': return 2; + case '3': return 3; + case '4': return 4; + case '5': return 5; + case '6': return 6; + case '7': return 7; + case '8': return 8; + case '9': return 9; + case 'a': case 'A': return 10; + case 'b': case 'B': return 11; + case 'c': case 'C': return 12; + case 'd': case 'D': return 13; + case 'e': case 'E': return 14; + case 'f': case 'F': return 15; + default: return 0; + } } /* Split a line into arguments, where every argument can be in the @@ -622,113 +622,113 @@ int hex_digit_to_int(char c) { * as in: "foo"bar or "foo' */ sds *sdssplitargs(const char *line, int *argc) { - const char *p = line; - char *current = NULL; - char **vector = NULL; - - *argc = 0; - while(1) { - /* skip blanks */ - while(*p && isspace(*p)) p++; - if (*p) { - /* get a token */ - int inq=0; /* set to 1 if we are in "quotes" */ - int insq=0; /* set to 1 if we are in 'single quotes' */ - int done=0; - - if (current == NULL) current = sdsempty(); - while(!done) { - if (inq) { - if (*p == '\\' && *(p+1) == 'x' && - is_hex_digit(*(p+2)) && - is_hex_digit(*(p+3))) - { - unsigned char byte; - - byte = (hex_digit_to_int(*(p+2))*16)+ - hex_digit_to_int(*(p+3)); - current = sdscatlen(current,(char*)&byte,1); - p += 3; - } else if (*p == '\\' && *(p+1)) { - char c; - - p++; - switch(*p) { - case 'n': c = '\n'; break; - case 'r': c = '\r'; break; - case 't': c = '\t'; break; - case 'b': c = '\b'; break; - case 'a': c = '\a'; break; - default: c = *p; break; - } - current = sdscatlen(current,&c,1); - } else if (*p == '"') { - /* closing quote must be followed by a space or - * nothing at all. */ - if (*(p+1) && !isspace(*(p+1))) goto err; - done=1; - } else if (!*p) { - /* unterminated quotes */ - goto err; - } else { - current = sdscatlen(current,p,1); - } - } else if (insq) { - if (*p == '\\' && *(p+1) == '\'') { - p++; - current = sdscatlen(current,"'",1); - } else if (*p == '\'') { - /* closing quote must be followed by a space or - * nothing at all. */ - if (*(p+1) && !isspace(*(p+1))) goto err; - done=1; - } else if (!*p) { - /* unterminated quotes */ - goto err; - } else { - current = sdscatlen(current,p,1); - } - } else { - switch(*p) { - case ' ': - case '\n': - case '\r': - case '\t': - case '\0': - done=1; - break; - case '"': - inq=1; - break; - case '\'': - insq=1; - break; - default: - current = sdscatlen(current,p,1); - break; - } - } - if (*p) p++; - } - /* add the token to the vector */ - vector = realloc(vector,((*argc)+1)*sizeof(char*)); - vector[*argc] = current; - (*argc)++; - current = NULL; - } else { - /* Even on empty input string return something not NULL. */ - if (vector == NULL) vector = malloc(sizeof(void*)); - return vector; - } - } + const char *p = line; + char *current = NULL; + char **vector = NULL; + + *argc = 0; + while(1) { + /* skip blanks */ + while(*p && isspace(*p)) p++; + if (*p) { + /* get a token */ + int inq=0; /* set to 1 if we are in "quotes" */ + int insq=0; /* set to 1 if we are in 'single quotes' */ + int done=0; + + if (current == NULL) current = sdsempty(); + while(!done) { + if (inq) { + if (*p == '\\' && *(p+1) == 'x' && + is_hex_digit(*(p+2)) && + is_hex_digit(*(p+3))) + { + unsigned char byte; + + byte = (hex_digit_to_int(*(p+2))*16)+ + hex_digit_to_int(*(p+3)); + current = sdscatlen(current,(char*)&byte,1); + p += 3; + } else if (*p == '\\' && *(p+1)) { + char c; + + p++; + switch(*p) { + case 'n': c = '\n'; break; + case 'r': c = '\r'; break; + case 't': c = '\t'; break; + case 'b': c = '\b'; break; + case 'a': c = '\a'; break; + default: c = *p; break; + } + current = sdscatlen(current,&c,1); + } else if (*p == '"') { + /* closing quote must be followed by a space or + * nothing at all. */ + if (*(p+1) && !isspace(*(p+1))) goto err; + done=1; + } else if (!*p) { + /* unterminated quotes */ + goto err; + } else { + current = sdscatlen(current,p,1); + } + } else if (insq) { + if (*p == '\\' && *(p+1) == '\'') { + p++; + current = sdscatlen(current,"'",1); + } else if (*p == '\'') { + /* closing quote must be followed by a space or + * nothing at all. */ + if (*(p+1) && !isspace(*(p+1))) goto err; + done=1; + } else if (!*p) { + /* unterminated quotes */ + goto err; + } else { + current = sdscatlen(current,p,1); + } + } else { + switch(*p) { + case ' ': + case '\n': + case '\r': + case '\t': + case '\0': + done=1; + break; + case '"': + inq=1; + break; + case '\'': + insq=1; + break; + default: + current = sdscatlen(current,p,1); + break; + } + } + if (*p) p++; + } + /* add the token to the vector */ + vector = realloc(vector,((*argc)+1)*sizeof(char*)); + vector[*argc] = current; + (*argc)++; + current = NULL; + } else { + /* Even on empty input string return something not NULL. */ + if (vector == NULL) vector = malloc(sizeof(void*)); + return vector; + } + } err: - while((*argc)--) - sdsfree(vector[*argc]); - free(vector); - if (current) sdsfree(current); - *argc = 0; - return NULL; + while((*argc)--) + sdsfree(vector[*argc]); + free(vector); + if (current) sdsfree(current); + *argc = 0; + return NULL; } /* Modify the string substituting all the occurrences of the set of @@ -741,42 +741,40 @@ err: * The function returns the sds string pointer, that is always the same * as the input pointer since no resize is needed. */ sds sdsmapchars(sds s, const char *from, const char *to, size_t setlen) { - size_t j, i, l = sdslen(s); + size_t j, i, l = sdslen(s); - for (j = 0; j < l; j++) { - for (i = 0; i < setlen; i++) { - if (s[j] == from[i]) { - s[j] = to[i]; - break; - } - } - } - return s; + for (j = 0; j < l; j++) { + for (i = 0; i < setlen; i++) { + if (s[j] == from[i]) { + s[j] = to[i]; + break; + } + } + } + return s; } /* Join an array of C strings using the specified separator (also a C string). * Returns the result as an sds string. */ sds sdsjoin(char **argv, int argc, char *sep, size_t seplen) { - sds join = sdsempty(); - int j; + sds join = sdsempty(); + int j; - for (j = 0; j < argc; j++) { - join = sdscat(join, argv[j]); - if (j != argc-1) join = sdscatlen(join,sep,seplen); - } - return join; + for (j = 0; j < argc; j++) { + join = sdscat(join, argv[j]); + if (j != argc-1) join = sdscatlen(join,sep,seplen); + } + return join; } /* Like sdsjoin, but joins an array of SDS strings. */ sds sdsjoinsds(sds *argv, int argc, const char *sep, size_t seplen) { - sds join = sdsempty(); - int j; + sds join = sdsempty(); + int j; - for (j = 0; j < argc; j++) { - join = sdscatsds(join, argv[j]); - if (j != argc-1) join = sdscatlen(join,sep,seplen); - } - return join; + for (j = 0; j < argc; j++) { + join = sdscatsds(join, argv[j]); + if (j != argc-1) join = sdscatlen(join,sep,seplen); + } + return join; } - - @@ -36,23 +36,23 @@ typedef char *sds; struct sdshdr { - int len; - int free; - char buf[]; + int len; + int free; + char buf[]; }; static inline struct sdshdr * sdsheader(const sds s) { - return s - (sizeof (struct sdshdr)); + return s - (sizeof (struct sdshdr)); } static inline size_t sdslen(const sds s) { - struct sdshdr *sh = sdsheader(s); - return sh->len; + struct sdshdr *sh = sdsheader(s); + return sh->len; } static inline size_t sdsavail(const sds s) { - struct sdshdr *sh = sdsheader(s); - return sh->free; + struct sdshdr *sh = sdsheader(s); + return sh->free; } sds sdsnewlen(const void *init, size_t initlen); |