/* Append the specified binary-safe string pointed by 't' of 'len' bytes to the * end of the specified sds string 's'. * * 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 sds_cat_len(sds s, const void *t, size_t len) { struct sdshdr *sh; size_t curlen = sds_len(s); s = sds_make_room_for(s,len); if (s == NULL) return NULL; sh = (void*) (s-(sizeof(struct sdshdr))); memcpy(s+curlen, t, len); sh->len = curlen+len; sh->free = sh->free-len; s[curlen+len] = '\0'; return s; }
dictEntry* dict_find(dict *d, void *key) { unsigned idx, h; dictEntry *he; h = dict_genhashfunction((sds)key,sds_len((sds)key)); idx = h & d->ht.sizemask; he = d->ht.table[idx]; DD("key = %s he->key = %s", key, he->key); while(he) { if(dict_comparekeys(d, key, he->key) == 0) return he; he = he->next; } return NULL; }
/* Enlarge the free space at the end of the sds string so that the caller * is sure that after calling this function can overwrite up to addlen * bytes after the end of the string, plus one more byte for nul term. * * Note: this does not change the *length* of the sds string as returned * by sds_len(), but only the free buffer space we have. */ sds sds_make_room_for(sds s, size_t addlen) { struct sdshdr *sh, *newsh; size_t free = sds_avail(s); size_t len, newlen; if (free >= addlen) return s; len = sds_len(s); sh = (void*) (s-(sizeof(struct sdshdr))); newlen = (len + addlen); if (newlen < SDS_MAX_PREALLOC) newlen *= 2; else newlen += SDS_MAX_PREALLOC; newsh = zrealloc(sh, sizeof(struct sdshdr)+newlen+1); if (newsh == NULL) return NULL; newsh->free = newlen - len; return newsh->buf; }
static int _dict_keyindex(dict *d, const void *key) { unsigned idx, h; dictEntry *he; if(_dict_expand_ifneed(d) == DICT_ERR) return -1; h = dict_genhashfunction((sds)key,sds_len((sds)key)); idx = h & d->ht.sizemask; he = d->ht.table[idx]; while(he) { /*if the key already exists , -1 is returned*/ if(dict_comparekeys(d, key, he->key) == 0) return KEY_EXISTS; he = he->next; } return idx; }
/* This function is similar to sds_cat_printf, but much faster as it does * not rely on sprintf() family functions implemented by the libc that * are often very slow. Moreover directly handling the sds string as * new data is concatenated provides a performance improvement. * * However this function only handles an incompatible subset of printf-alike * format specifiers: * * %s - C String * %S - SDS string * %i - signed int * %I - 64 bit signed integer (long long, int64_t) * %u - unsigned int * %U - 64 bit unsigned integer (unsigned long long, uint64_t) * %% - Verbatim "%" character. */ sds sds_cat_fmt(sds s, char const *fmt, ...) { struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr))); size_t initlen = sds_len(s); const char *f = fmt; int i; va_list ap; va_start(ap,fmt); f = fmt; /* Next format specifier byte to process. */ i = initlen; /* Position of the next byte to write to dest str. */ while(*f) { char next, *str; unsigned int l; long long num; unsigned long long unum; /* Make sure there is always space for at least 1 char. */ if (sh->free == 0) { s = sds_make_room_for(s,1); sh = (void*) (s-(sizeof(struct sdshdr))); } switch(*f) { case '%': next = *(f+1); f++; switch(next) { case 's': case 'S': str = va_arg(ap,char*); l = (next == 's') ? strlen(str) : sds_len(str); if (sh->free < l) { s = sds_make_room_for(s,l); sh = (void*) (s-(sizeof(struct sdshdr))); } memcpy(s+i,str,l); sh->len += l; sh->free -= l; i += l; break; case 'i': case 'I': if (next == 'i') num = va_arg(ap,int); else num = va_arg(ap,long long); { char buf[SDS_LLSTR_SIZE]; l = sdsll2str(buf,num); if (sh->free < l) { s = sds_make_room_for(s,l); sh = (void*) (s-(sizeof(struct sdshdr))); } memcpy(s+i,buf,l); sh->len += l; sh->free -= l; i += l; } break; case 'u': case 'U': if (next == 'u') unum = va_arg(ap,unsigned int); else unum = va_arg(ap,unsigned long long); { char buf[SDS_LLSTR_SIZE]; l = sdsull2str(buf,unum); if (sh->free < l) { s = sds_make_room_for(s,l); sh = (void*) (s-(sizeof(struct sdshdr))); } memcpy(s+i,buf,l); sh->len += l; sh->free -= l; i += l; } break; default: /* Handle %% and generally %<unknown>. */ s[i++] = next; sh->len += 1; sh->free -= 1; break; } break; default: s[i++] = *f; sh->len += 1; sh->free -= 1; break; }
/* Append the specified sds 't' to the existing sds 's'. * * 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 sds_cat_sds(sds s, const sds t) { return sds_cat_len(s, t, sds_len(t)); }
/* Duplicate an sds string. */ sds sds_dup(const sds s) { return sds_new_len(s, sds_len(s)); }