]> mj.ucw.cz Git - libucw.git/commitdiff
bgets_mp(): Rewritten implementation.
authorPavel Charvat <pchar@ucw.cz>
Wed, 10 Jan 2018 11:44:05 +0000 (12:44 +0100)
committerPavel Charvat <pchar@ucw.cz>
Wed, 10 Jan 2018 11:44:05 +0000 (12:44 +0100)
ucw/fastbuf.h
ucw/ff-string.c

index 77e5ecb0b81a9ef465e0bbb888f3503cd41082be..0a04176a0f8ec18155996d9a6c3b5e1d55e4da41 100644 (file)
@@ -752,7 +752,6 @@ struct bb_t;
 uint bgets_bb(struct fastbuf *f, struct bb_t *b, uint limit);
 /**
  * Read a string, strip the trailing `\n` and store it into buffer allocated from a memory pool.
- * CAVEAT: Internally allocates the whole line on stack -> can segfault if too long.
  **/
 char *bgets_mp(struct fastbuf *f, struct mempool *mp);
 
index d3aff87ce9ee7f1c792ce00e98d41af1e56d6e35..d4dafede693ba0ed50dc0e45367bc49236b477b0 100644 (file)
@@ -2,7 +2,7 @@
  *     UCW Library -- Fast Buffered I/O: Strings
  *
  *     (c) 1997--2006 Martin Mares <mj@ucw.cz>
- *     (c) 2006 Pavel Charvat <pchar@ucw.cz>
+ *     (c) 2006--2018 Pavel Charvat <pchar@ucw.cz>
  *
  *     This software may be freely distributed and used according to the terms
  *     of the GNU Lesser General Public License.
@@ -135,17 +135,11 @@ bgets_mp(struct fastbuf *f, struct mempool *mp)
   uint src_len = bdirect_read_prepare(f, &src);
   if (!src_len)
     return NULL;
-#define BLOCK_SIZE (4096 - sizeof(void *))
-  struct block {
-    struct block *prev;
-    byte data[BLOCK_SIZE];
-  } *blocks = NULL;
-  uint sum = 0, buf_len = BLOCK_SIZE, cnt;
-  struct block first_block, *new_block = &first_block;
-  byte *buf = new_block->data;
+  byte *buf = mp_start_noalign(mp, 1);
+  size_t buf_len = mp_avail(mp);
   do
     {
-      cnt = MIN(src_len, buf_len);
+      uint cnt = MIN(src_len, buf_len);
       for (uint i = cnt; i--;)
         {
          byte v = *src++;
@@ -165,29 +159,17 @@ bgets_mp(struct fastbuf *f, struct mempool *mp)
        src_len -= cnt;
       if (cnt == buf_len)
         {
-          new_block->prev = blocks;
-          blocks = new_block;
-          sum += buf_len = BLOCK_SIZE;
-         new_block = alloca(sizeof(struct block));
-         buf = new_block->data;
+         buf = mp_spread(mp, buf, 1);
+         buf_len = mp_avail(mp) - (buf - (byte *)mp_ptr(mp));
        }
       else
        buf_len -= cnt;
     }
   while (src_len);
-exit: ;
-  uint len = buf - new_block->data;
-  byte *result = mp_alloc(mp, sum + len + 1) + sum;
-  result[len] = 0;
-  memcpy(result, new_block->data, len);
-  while (blocks)
-    {
-      result -= BLOCK_SIZE;
-      memcpy(result, blocks->data, BLOCK_SIZE);
-      blocks = blocks->prev;
-    }
-  return result;
-#undef BLOCK_SIZE
+exit:
+  buf = mp_spread(mp, buf, 1);
+  *buf++ = 0;
+  return mp_end(mp, buf);
 }
 
 char *