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 sdslen(), but only the free buffer space we have. */
| 231 | * Note: this does not change the *length* of the sds string as returned |
| 232 | * by sdslen(), but only the free buffer space we have. */ |
| 233 | sds sdsMakeRoomFor(sds s, size_t addlen) { |
| 234 | void *sh, *newsh; |
| 235 | size_t avail = sdsavail(s); |
| 236 | size_t len, newlen, reqlen; |
| 237 | char type, oldtype = s[-1] & SDS_TYPE_MASK; |
| 238 | int hdrlen; |
| 239 | size_t usable; |
| 240 | |
| 241 | /* Return ASAP if there is enough space left. */ |
| 242 | if (avail >= addlen) return s; |
| 243 | |
| 244 | len = sdslen(s); |
| 245 | sh = (char*)s-sdsHdrSize(oldtype); |
| 246 | reqlen = newlen = (len+addlen); |
| 247 | assert(newlen > len); /* Catch size_t overflow */ |
| 248 | if (newlen < SDS_MAX_PREALLOC) |
| 249 | newlen *= 2; |
| 250 | else |
| 251 | newlen += SDS_MAX_PREALLOC; |
| 252 | |
| 253 | type = sdsReqType(newlen); |
| 254 | |
| 255 | /* Don't use type 5: the user is appending to the string and type 5 is |
| 256 | * not able to remember empty space, so sdsMakeRoomFor() must be called |
| 257 | * at every appending operation. */ |
| 258 | if (type == SDS_TYPE_5) type = SDS_TYPE_8; |
| 259 | |
| 260 | hdrlen = sdsHdrSize(type); |
| 261 | assert(hdrlen + newlen + 1 > reqlen); /* Catch size_t overflow */ |
| 262 | if (oldtype==type) { |
| 263 | newsh = s_realloc_usable(sh, hdrlen+newlen+1, &usable); |
| 264 | if (newsh == NULL) return NULL; |
| 265 | s = (char*)newsh+hdrlen; |
| 266 | } else { |
| 267 | /* Since the header size changes, need to move the string forward, |
| 268 | * and can't use realloc */ |
| 269 | newsh = s_malloc_usable(hdrlen+newlen+1, &usable); |
| 270 | if (newsh == NULL) return NULL; |
| 271 | memcpy((char*)newsh+hdrlen, s, len+1); |
| 272 | s_free(sh); |
| 273 | s = (char*)newsh+hdrlen; |
| 274 | s[-1] = type; |
| 275 | sdssetlen(s, len); |
| 276 | } |
| 277 | usable = usable-hdrlen-1; |
| 278 | if (usable > sdsTypeMaxSize(type)) |
| 279 | usable = sdsTypeMaxSize(type); |
| 280 | sdssetalloc(s, usable); |
| 281 | return s; |
| 282 | } |
| 283 | |
| 284 | /* Reallocate the sds string so that it has no free space at the end. The |
| 285 | * contained string remains not altered, but next concatenation operations |
no test coverage detected