Welcome to little lamb

Code » limb » commit 1d089d0

buffer_putescall(): Fix interface & error cases

author Olivier Brunel
2023-05-04 17:38:12 UTC
committer Olivier Brunel
2023-05-20 18:06:40 UTC
parent 2c8223625309ee476494c03e736b13141027ebd8

buffer_putescall(): Fix interface & error cases

- First off the interface wasn't right, so let's make it ok/clear. Since
  it's a special case where how much data is written might be different
  (i.e. more) than is read, let's take two pointers.
  Once will be how much has been actually written into the buffer, the
  other will be how much has been read from the source. It also serves
  as an initial offset as before.

- Second, error case wasn't properly handled since we tried to flush the
  buffer when not all we wanted was written, but then discarded the
  missing bit only to move on to the next data to read.
  So now if not everything could be put into the buffer, we do flush it
  and check whether it's still full. If not, we continue what had been
  interrupted and go on. If it is (still full), we "unput" whatever was
  put (since it was a partial thing), before erroring out.

src/doc/buffer.h/buffer_putescall.3.md +9 -9
src/liblimb/buffer.h/buffer_putesc.c +2 -2
src/liblimb/buffer.h/buffer_putescall.c +19 -12
src/liblimb/include/limb/buffer.h +1 -1

diff --git a/src/doc/buffer.h/buffer_putescall.3.md b/src/doc/buffer.h/buffer_putescall.3.md
index 2bbabee..714f222 100644
--- a/src/doc/buffer.h/buffer_putescall.3.md
+++ b/src/doc/buffer.h/buffer_putescall.3.md
@@ -11,7 +11,7 @@ buffer
     #include <limb/buffer.h>
 
 ```pre hl
-size_t buffer_putescall(buffer *<em>b</em>, const char *<em>s</em>, size_t <em>len</em>, size_t *<em>pos</em>)
+int buffer_putescall(buffer *<em>b</em>, const char *<em>s</em>, size_t <em>len</em>, size_t *<em>w</em>, size_t *<em>r</em>)
 ssize_t buffer_putesc(buffer *<em>b</em>, const char *<em>s</em>, size_t <em>len</em>)
 ssize_t buffer_putescs(buffer *<em>b</em>, const char *<em>s</em>)
 ```
@@ -19,12 +19,13 @@ ssize_t buffer_putescs(buffer *<em>b</em>, const char *<em>s</em>)
 # DESCRIPTION
 
 The `buffer_putescall`() function will write the content of `s` of length `len`
-starting at position pointed by `pos` (usually 0) into buffer `b`, whilst
+starting at position pointed by `r` (usually 0) into buffer `b`, whilst
 taking care of escaping characters as needed. This means more characters might
 be written into `b` than present in `s`.
 
-The value pointed by `pos` will be updated to reflect the position inside
-`s` afterwards.
+The value pointed by `r` will be updated to reflect the position inside
+`s` afterwards, while the value pointed by `w` will be updated with the length
+actually written into the buffer.
 
 The `buffer_putesc`() function does the same always processing `s` from the
 start.
@@ -36,12 +37,11 @@ For more about the escaping performed, refer to [esc_fmt](3).
 
 # RETURN VALUE
 
-The `buffer_putescall`() function returns the number of bytes written into `b`
-on success, which can be more than processed from `s` due to the escaping.
-Otherwise, it returns 0 and sets `errno` to indicate the error.
+The `buffer_putescall`() function returns 1 on success, otherwise it returns 0
+and sets `errno` to indicate the error.
 
 The `buffer_putesc`() and `buffer_putescs`() functions return the number of
-bytes processed from `s` on success. Otherwise they returns -1 and sets `errno`
+bytes written into `buf` on success. Otherwise they returns -1 and sets `errno`
 to indicate the error.
 
 # ERRORS
@@ -49,7 +49,7 @@ to indicate the error.
 The `buffer_putescall`() function may fail if :
 
 : *EINVAL*
-:: `pos` was too high
+:: `r` was too high (i.e. more than `len`).
 
 All of these may also fail and set `errno` for any of the errors specified for
 [buffer_flush](3).
diff --git a/src/liblimb/buffer.h/buffer_putesc.c b/src/liblimb/buffer.h/buffer_putesc.c
index ecff395..49a7c3b 100644
--- a/src/liblimb/buffer.h/buffer_putesc.c
+++ b/src/liblimb/buffer.h/buffer_putesc.c
@@ -7,8 +7,8 @@
 ssize_t
 buffer_putesc(buffer *b, const char *s, size_t len)
 {
-    size_t w = 0;
-    if (!buffer_putescall(b, s, len, &w))
+    size_t w, r = 0;
+    if (!buffer_putescall(b, s, len, &w, &r))
         return -1;
     return w;
 }
diff --git a/src/liblimb/buffer.h/buffer_putescall.c b/src/liblimb/buffer.h/buffer_putescall.c
index a8681db..27dbed1 100644
--- a/src/liblimb/buffer.h/buffer_putescall.c
+++ b/src/liblimb/buffer.h/buffer_putescall.c
@@ -5,24 +5,31 @@
 #include <limb/buffer.h>
 #include <limb/esc.h>
 
-size_t
-buffer_putescall(buffer *b, const char *s, size_t len, size_t *pos)
+int
+buffer_putescall(buffer *b, const char *s, size_t len, size_t *w, size_t *r)
 {
-    if (*pos > len) return (errno = EINVAL, 0);
-    size_t written = 0;
+    if (*r > len) return (errno = EINVAL, 0);
 
-    for (;;) {
+    *w = 0;
+    while (*r < len) {
         char buf[64];
-        size_t w = 0;
+        size_t realw, realr;
 
-        escall_fmt(buf, sizeof(buf), s, len, &w, pos);
-        written += buffer_putnoflush(b, buf, w);
-        if (*pos >= len) return written;
-
-        if (buffer_isfull(b)) {
+        realr = *r;
+        realw = 0;
+        escall_fmt(buf, sizeof(buf), s, len, &realw, &realr);
+        for (size_t p = 0; ; ) {
+            p += buffer_putnoflush(b, buf + p, realw - p);
+            if (p == realw)
+                break;
             buffer_flush(b);
-            if (buffer_isfull(b))
+            if (buffer_isfull(b)) {
+                buffer_unput(b, p);
                 return 0;
+            }
         }
+        *r = realr;
+        *w += realw;
     }
+    return 1;
 }
diff --git a/src/liblimb/include/limb/buffer.h b/src/liblimb/include/limb/buffer.h
index a6a3be6..6365b28 100644
--- a/src/liblimb/include/limb/buffer.h
+++ b/src/liblimb/include/limb/buffer.h
@@ -41,7 +41,7 @@
 /* Writing */
 
 extern void buffer_putmsg(buffer *b, const char * const *as, unsigned int n);
-extern size_t buffer_putescall(buffer *b, const char *s, size_t len, size_t *pos);
+extern int buffer_putescall(buffer *b, const char *s, size_t len, size_t *w, size_t *r);
 extern ssize_t buffer_putesc(buffer *b, const char *s, size_t len);
 extern ssize_t buffer_putescs(buffer *b, const char *s);
 extern ssize_t buffer_puthex(buffer *b, const void *data, size_t dlen, int options);