OSSP CVS Repository

ossp - Difference in ossp-pkg/sio/al.c versions 1.8 and 1.9
Not logged in
[Honeypot]  [Browse]  [Home]  [Login]  [Reports
[Search]  [Ticket]  [Timeline
  [History

ossp-pkg/sio/al.c 1.8 -> 1.9

--- al.c 2002/10/14 15:44:03     1.8
+++ al.c 2002/10/15 13:13:06     1.9
@@ -507,6 +507,9 @@
 
 /*
  * copy bytes into buffer, FIFO
+ *
+ * stops copy operation when a new buffer cannot be created
+ * but leaves data structure consistent
  */
 al_rc_t al_append_bytes(al_t *al, const char *src, size_t n)
 {
@@ -516,15 +519,19 @@
     size_t res, step;
     char *dst;
 
+    /* argument sanity check(s) */
+    if (al == NULL || src == NULL || n < 0)
+            return AL_RC(AL_ERR_ARG);
+
     cur = TAIL(al,chunks);
     res = AL_CHUNK_RESERVE(cur);
 
     while (n > 0) {
         if (res == 0) {
             rc = new_buffer(al, &buf);
-            /* XXX handle error */
+            if (rc != AL_OK) return AL_RC(rc);
             rc = new_chunk(al,buf,&cur);
-            /* XXX handle error */
+            if (rc != AL_OK) return AL_RC(rc);
             res = AL_CHUNK_RESERVE(cur);
             ADDTAIL(al, chunks, cur);
         }
@@ -546,6 +553,9 @@
 
 /*
  * copy bytes into buffer, LIFO
+ *
+ * stops copy operation when a new buffer cannot be created
+ * but leaves data structure consistent
  */
 al_rc_t al_prepend_bytes(al_t *al, const char *src, size_t n)
 {
@@ -555,6 +565,10 @@
     size_t res, step;
     char *dst;
 
+    /* argument sanity check(s) */
+    if (al == NULL || src == NULL || n < 0)
+            return AL_RC(AL_ERR_ARG);
+
     cur = HEAD(al,chunks);
     res = AL_CHUNK_PRESERVE(cur);
 
@@ -563,9 +577,9 @@
     while (n > 0) {
         if (res == 0) {
             rc = new_buffer(al, &buf);
-            if (rc != AL_OK) return rc;
+            if (rc != AL_OK) return AL_RC(rc);
             rc = new_chunk(al,buf,&cur);
-            if (rc != AL_OK) return rc;
+            if (rc != AL_OK) return AL_RC(rc);
             res = AL_CHUNK_PRESERVE(cur);
             ADDHEAD(al, chunks, cur);
         }
@@ -599,10 +613,14 @@
     al_buffer_t *buf;
     al_chunk_t  *cur;
 
+    /* argument sanity check(s) */
+    if (al == NULL || p == NULL || n < 0)
+            return AL_RC(AL_ERR_ARG);
+
     rc = make_buffer(al, p, n, &buf);
-    if (rc != AL_OK) return rc;
+    if (rc != AL_OK) return AL_RC(rc);
     rc = new_chunk(al,buf, &cur);
-    if (rc != AL_OK) return rc;
+    if (rc != AL_OK) return AL_RC(rc);
     ADDTAIL(al, chunks, cur);
 
     /* validate data in buffer */
@@ -625,17 +643,51 @@
 al_rc_t al_splice(al_t *al, size_t off, size_t n, al_t *nal, al_t *tal)
 {
     al_rc_t rc;
-    al_chunk_t *cur, *next;
+    al_chunk_t *cur, *next, *ins, *splitbuf;
     size_t pos, skip, len, step;
+    int doinsert;
+
+    /* argument sanity check(s) */
+    if (al == NULL || n < 0)
+            return AL_RC(AL_ERR_ARG);
+
+    /* optimization: treat an empty list as no insertion at all */
+    doinsert = (nal != NULL) && !ISEMPTY(nal,chunks);
 
     /*
      * seek to beginning, return EOF when seek position does not exist
      * EOD must be a valid seek position so that we can append data
      */
     rc = al_seek(al, off, &cur, &skip);
-    if (rc != AL_OK) return rc;
+    if (rc != AL_OK) return AL_RC(rc);
+    
+    /*
+     * remember insertion point
+     *
+     * caveat: if the first chunk is removed from input the insertion
+     *         point shifts to the next chunk (or EOD -> NULL pointer)
+     */
+    ins = cur;
 
-    /* as long as there is data to move */
+    /*
+     * if the first chunk is not removed completely it needs to be
+     * split into two halves to allow insertion of new chunks later
+     * from nal
+     *
+     * splitting at this point preserves all data in case the
+     * allocation of the split buffer fails
+     */
+    if (doinsert) {
+        if (ins != NULL && skip > 0 && skip+n < AL_CHUNK_LEN(ins)) {
+            rc = split_chunk(al, ins, skip, &splitbuf);
+            if (rc != AL_OK) return AL_RC(rc);
+            INSERT(al,chunks,ins,splitbuf);
+        }
+    }
+
+    /*
+     * as long as there is data to move
+     */
     pos = off;
     while (n > 0 && cur != NULL) {
         next = NEXT(cur, chunks);
@@ -651,8 +703,22 @@
             /* compute number of bytes to process */
             step = AL_CHUNK_SPAN(cur, skip, n);
 
-            if (tal != NULL)
-                al_append_bytes(tal, AL_CHUNK_PTR(cur, skip), step);
+            /* copy data to target */
+            if (tal != NULL) {
+                /*
+                 * XXX - this operation can fail
+                 */
+                size_t before = tal->bytes;
+
+                rc = al_append_bytes(tal, AL_CHUNK_PTR(cur, skip), step);
+                if (rc != AL_OK) {
+                    /* correct step size to actual size */
+                    step = tal->bytes - before;
+                }
+
+            } else {
+                rc = AL_OK;
+            }
 
             /*
              * cut span from src chunk
@@ -674,6 +740,12 @@
                 AL_RESIZE(al, cur, -step);
             }
 
+            /*
+             * bail out from failed al_append_bytes operation above
+             *
+             */
+            if (rc != AL_OK) return AL_RC(rc);
+
         } else {
 
             /*
@@ -683,6 +755,18 @@
              */
             step = len;
             REMOVE(al, chunks, cur);
+
+            /*
+             * when the insertion point is removed, we have to adjust
+             * the insertion point
+             *
+             * if the insertion point was the last chunk we get a NULL
+             * next pointer and the insertion method switches to APPEND
+             * mode
+             */
+            if (cur == ins)
+                ins = next;
+
             al->bytes -= step;
             if (tal == NULL) {
                 dispose_chunk(al, cur);
@@ -701,39 +785,26 @@
     /*
      * now splice in replacement chunks
      */
-    if (nal && !ISEMPTY(nal,chunks)) {
-        al_chunk_t *ins;
-
-        /* rewind */
-        rc = al_seek(al, off, &ins, &skip);
-        if (rc != AL_OK) return rc;
-
-        if (ins == NULL) {
+    if (doinsert) {
 
+        if (ins != NULL) {
             /*
-             * simple case where list end is 'replaced'
+             * complex case where list is inserted
+             *
+             * the original list has already been modified so
+             * that we can simply insert between two chunks
              */
-            APPENDLIST(al,chunks,nal);
-
+            INSERTLIST(al,chunks,ins,nal);
         } else {
-
             /*
-             * if beginning and end were in same chunk we have to split this
-             * chunk in two for a copyless insert operation
+             * simple case where list end is 'replaced'
              */
-            if (skip > 0) {
-                al_chunk_t *twin;
-                rc = split_chunk(al, ins, skip, &twin);
-                if (rc != AL_OK) return rc;
-
-                INSERT(al,chunks,ins,twin);
-            }
-            INSERTLIST(al,chunks,ins,nal);
-
+            APPENDLIST(al,chunks,nal);
         }
 
         al->bytes += nal->bytes;
         nal->bytes = 0;
+
     }
 
     return AL_OK;
@@ -749,7 +820,7 @@
 
     txp = (al_tx_t*)(al->m.malloc)(sizeof(al_tx_t));
     if (txp == NULL)
-        return AL_ERR_MEM;
+        return AL_RC(AL_ERR_MEM);
 
     *txpp = txp;
     return AL_OK;
@@ -777,7 +848,7 @@
     txp->cur = NULL;
 
     rc = al_seek(al, off, &txp->cur, &txp->skip);
-    if (rc != AL_OK) return rc;
+    if (rc != AL_OK) return AL_RC(rc);
 
     txp->dir  = dir;
     txp->togo = n;
@@ -848,7 +919,7 @@
     al_chunk_t *view;
 
     rc = al_traverse(al, off, n, dir, &tx);
-    if (rc != AL_OK) return rc;
+    if (rc != AL_OK) return AL_RC(rc);
 
     while ((rc = al_traverse_next(al, &tx, &view)) == AL_OK) {
         rc = cb(view, u);
@@ -857,7 +928,7 @@
     }
 
     if (rc != AL_ERR_EOF)
-        return rc;
+        return AL_RC(rc);
 
     return AL_OK;
 }
@@ -879,7 +950,7 @@
     *lenp = 0; /* keep caller on safe side */
 
     rc = al_traverse(al, off, n, AL_FORWARD, &tx);
-    if (rc != AL_OK) return rc;
+    if (rc != AL_OK) return AL_RC(rc);
 
     total = 0;
     while ((rc = al_traverse_next(al, &tx, &view)) == AL_OK) {
@@ -891,7 +962,7 @@
     *lenp = total;
 
     if (rc != AL_ERR_EOF)
-        return rc;
+        return AL_RC(rc);
 
     return AL_OK;
 }
@@ -909,7 +980,7 @@
     size_t step;
 
     rc = al_traverse(al, off, n, AL_FORWARD, &tx);
-    if (rc != AL_OK) return rc;
+    if (rc != AL_OK) return AL_RC(rc);
 
     while ((rc = al_traverse_next(al, &tx, &view)) == AL_OK) {
         step = AL_CHUNK_LEN(view);
@@ -917,7 +988,7 @@
     }
 
     if (rc != AL_ERR_EOF)
-        return rc;
+        return AL_RC(rc);
 
     return AL_OK;
 }

CVSTrac 2.0.1