Mon, 25 Jul 2022 15:29:56 +0200
#184 #170 more thorough flush testing
Also adds proper doc for write function.
src/buffer.c | file | annotate | diff | comparison | revisions | |
src/cx/buffer.h | file | annotate | diff | comparison | revisions | |
test/test_buffer.cpp | file | annotate | diff | comparison | revisions |
1.1 --- a/src/buffer.c Mon Jul 25 14:16:49 2022 +0200 1.2 +++ b/src/buffer.c Mon Jul 25 15:29:56 2022 +0200 1.3 @@ -248,7 +248,8 @@ 1.4 // try again with the remaining stuff 1.5 unsigned char const *new_ptr = ptr; 1.6 new_ptr += items_flush * size; 1.7 - return cxBufferWrite(new_ptr, size, items_keep, buffer); 1.8 + // report the directly flushed items as written plus the remaining stuff 1.9 + return items_flush + cxBufferWrite(new_ptr, size, items_keep, buffer); 1.10 } else { 1.11 // all items have been flushed - report them as written 1.12 return nitems; 1.13 @@ -257,7 +258,7 @@ 1.14 // nothing could be flushed at all, we immediately give up without writing any data 1.15 return 0; 1.16 } else { 1.17 - // we were partially successful, we have shift left and try again 1.18 + // we were partially successful, we shift left and try again 1.19 cxBufferShiftLeft(buffer, flush_pos); 1.20 return cxBufferWrite(ptr, size, nitems, buffer); 1.21 }
2.1 --- a/src/cx/buffer.h Mon Jul 25 14:16:49 2022 +0200 2.2 +++ b/src/cx/buffer.h Mon Jul 25 15:29:56 2022 +0200 2.3 @@ -310,7 +310,20 @@ 2.4 /** 2.5 * Writes data to a CxBuffer. 2.6 * 2.7 - * The position of the buffer is increased by the number of bytes written. 2.8 + * If flushing is enabled and the buffer needs to flush, the data is flushed to 2.9 + * the target until the target signals that it cannot take more data by 2.10 + * returning zero via the respective write function. In that case, the remaining 2.11 + * data in this buffer is shifted to the beginning of this buffer so that the 2.12 + * newly available space can be used to append as much data as possible. This 2.13 + * function only stops writing more elements, when the flush target and this 2.14 + * buffer are both incapable of taking more data or all data has been written. 2.15 + * The number returned by this function is the total number of elements that 2.16 + * could be written during the process. It does not necessarily mean that those 2.17 + * elements are still in this buffer, because some of them could have also be 2.18 + * flushed already. 2.19 + * 2.20 + * If automatic flushing is not enabled, the position of the buffer is increased 2.21 + * by the number of bytes written. 2.22 * 2.23 * \note The signature is compatible with the fwrite() family of functions. 2.24 *
3.1 --- a/test/test_buffer.cpp Mon Jul 25 14:16:49 2022 +0200 3.2 +++ b/test/test_buffer.cpp Mon Jul 25 15:29:56 2022 +0200 3.3 @@ -351,6 +351,23 @@ 3.4 } 3.5 }; 3.6 3.7 +static size_t mock_write_limited_rate( 3.8 + void const *ptr, 3.9 + size_t size, 3.10 + __attribute__((unused)) size_t nitems, 3.11 + CxBuffer *buffer 3.12 +) { 3.13 + // simulate limited target drain capacity 3.14 + static bool full = false; 3.15 + if (full) { 3.16 + full = false; 3.17 + return 0; 3.18 + } else { 3.19 + full = true; 3.20 + return cxBufferWrite(ptr, size, nitems > 2 ? 2 : nitems, buffer); 3.21 + } 3.22 +} 3.23 + 3.24 TEST_F(BufferWrite, SizeOneFit) { 3.25 const char *data = "test"; 3.26 ASSERT_EQ(buf.capacity, 8); 3.27 @@ -595,6 +612,33 @@ 3.28 EXPECT_EQ(memcmp(target.space, "prepfoobarhello", 15), 0); 3.29 } 3.30 3.31 +TEST_F(BufferWrite, FlushRateLimited) { 3.32 + enableFlushing(); 3.33 + // limit the rate of the flush function and the capacity of the target 3.34 + target.capacity = 16; 3.35 + target.flags &= ~CX_BUFFER_AUTO_EXTEND; 3.36 + buf.flush_func = (cx_write_func) mock_write_limited_rate; 3.37 + ASSERT_EQ(buf.capacity, 8); 3.38 + ASSERT_EQ(buf.pos, 4); 3.39 + size_t written = cxBufferWrite("foo", 1, 3, &buf); 3.40 + EXPECT_EQ(written, 3); 3.41 + ASSERT_EQ(buf.pos, 7); 3.42 + ASSERT_EQ(buf.size, 7); 3.43 + ASSERT_EQ(target.pos, 0); 3.44 + ASSERT_EQ(target.size, 0); 3.45 + written = cxBufferWrite("hello, world!", 1, 13, &buf); 3.46 + // " world!" fits into this buffer, the remaining stuff is flushed out 3.47 + EXPECT_EQ(written, 13); 3.48 + EXPECT_EQ(buf.pos, 7); 3.49 + EXPECT_EQ(buf.size, 7); 3.50 + EXPECT_EQ(buf.capacity, 8); 3.51 + EXPECT_EQ(memcmp(buf.space, " world!", 7), 0); 3.52 + EXPECT_EQ(target.pos, 13); 3.53 + ASSERT_EQ(target.size, 13); 3.54 + EXPECT_EQ(target.capacity, 16); 3.55 + EXPECT_EQ(memcmp(target.space, "prepfoohello,", 13), 0); 3.56 +} 3.57 + 3.58 class BufferSeek : public BufferFixture { 3.59 }; 3.60