]> git.saurik.com Git - redis.git/commitdiff
sdsMakeRoomFor() exposed as public API. sdsIncrLen() added. Both the changes make...
authorantirez <antirez@gmail.com>
Wed, 2 Nov 2011 15:50:59 +0000 (16:50 +0100)
committerantirez <antirez@gmail.com>
Wed, 2 Nov 2011 15:50:59 +0000 (16:50 +0100)
src/sds.c
src/sds.h

index fc104a4a087674631385bcf74779fa9e5d8a4607..c3a0ccb978ae92b56a69a5c9d9964ba69784fc0a 100644 (file)
--- a/src/sds.c
+++ b/src/sds.c
@@ -40,6 +40,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <ctype.h>
 #include <stdlib.h>
 #include <string.h>
 #include <ctype.h>
+#include <assert.h>
 #include "sds.h"
 #include "zmalloc.h"
 
 #include "sds.h"
 #include "zmalloc.h"
 
@@ -107,7 +108,7 @@ void sdsclear(sds s) {
  * 
  * Note: this does not change the *size* of the sds string as returned
  * by sdslen(), but only the free buffer space we have. */
  * 
  * Note: this does not change the *size* of the sds string as returned
  * by sdslen(), but only the free buffer space we have. */
-static sds sdsMakeRoomFor(sds s, size_t addlen) {
+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;
@@ -127,6 +128,37 @@ static sds sdsMakeRoomFor(sds s, size_t addlen) {
     return newsh->buf;
 }
 
     return newsh->buf;
 }
 
+/* Increment the sds length and decrements the left free space at the
+ * end of the string accordingly to 'incr'. Also set the null term
+ * in the new end of the string.
+ *
+ * This function is used in order to fix the string length after the
+ * user calls sdsMakeRoomFor(), writes something after the end of
+ * the current string, and finally needs to set the new length.
+ *
+ * Note: it is possible to use a negative increment in order to
+ * right-trim the string.
+ *
+ * Using sdsIncrLen() and sdsMakeRoomFor() it is possible to mount the
+ * following schema to cat bytes coming from the kerenl to the end of an
+ * sds string new things without copying into an intermediate buffer:
+ *
+ * oldlen = sdslen(s);
+ * s = sdsMakeRoomFor(s, BUFFER_SIZE);
+ * nread = read(fd, s+oldlen, BUFFER_SIZE);
+ * ... check for nread <= 0 and handle it ...
+ * sdsIncrLen(s, nhread);
+ */
+void sdsIncrLen(sds s, int incr) {
+    struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr)));
+
+    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
  * the original length of the sds will be set to zero. */
 sds sdsgrowzero(sds s, size_t len) {
 /* Grow the sds to have the specified length. Bytes that were not part of
  * the original length of the sds will be set to zero. */
 sds sdsgrowzero(sds s, size_t len) {
@@ -615,6 +647,7 @@ sds sdsmapchars(sds s, char *from, char *to, size_t setlen) {
 
 int main(void) {
     {
 
 int main(void) {
     {
+        struct sdshdr *sh;
         sds x = sdsnew("foo"), y;
 
         test_cond("Create a string and obtain the length",
         sds x = sdsnew("foo"), y;
 
         test_cond("Create a string and obtain the length",
@@ -694,7 +727,26 @@ int main(void) {
         x = sdsnew("aar");
         y = sdsnew("bar");
         test_cond("sdscmp(bar,bar)", sdscmp(x,y) < 0)
         x = sdsnew("aar");
         y = sdsnew("bar");
         test_cond("sdscmp(bar,bar)", sdscmp(x,y) < 0)
+
+        {
+            int oldfree;
+
+            sdsfree(x);
+            x = sdsnew("0");
+            sh = (void*) (x-(sizeof(struct sdshdr)));
+            test_cond("sdsnew() free/len buffers", sh->len == 1 && sh->free == 0);
+            x = sdsMakeRoomFor(x,1);
+            sh = (void*) (x-(sizeof(struct sdshdr)));
+            test_cond("sdsMakeRoomFor()", sh->len == 1 && sh->free > 0);
+            oldfree = sh->free;
+            x[1] = '1';
+            sdsIncrLen(x,1);
+            test_cond("sdsIncrLen() -- content", x[0] == '0' && x[1] == '1');
+            test_cond("sdsIncrLen() -- len", sh->len == 2);
+            test_cond("sdsIncrLen() -- free", sh->free == oldfree-1);
+        }
     }
     test_report()
     }
     test_report()
+    return 0;
 }
 #endif
 }
 #endif
index 6e5684eeb913e370f2c0907ac15262622d19873e..eff1b03e800bafa1232e25e3b585c6c75070ff26 100644 (file)
--- a/src/sds.h
+++ b/src/sds.h
@@ -88,4 +88,8 @@ sds *sdssplitargs(char *line, int *argc);
 void sdssplitargs_free(sds *argv, int argc);
 sds sdsmapchars(sds s, char *from, char *to, size_t setlen);
 
 void sdssplitargs_free(sds *argv, int argc);
 sds sdsmapchars(sds s, char *from, char *to, size_t setlen);
 
+/* Low level functions exposed to the user API */
+sds sdsMakeRoomFor(sds s, size_t addlen);
+void sdsIncrLen(sds s, int incr);
+
 #endif
 #endif