8 #include "test_suite.h"
11 buf_t
buf_new(size_t sz
) {
12 buf_t buf
= malloc(sz
+ sizeof *buf
);
15 buf
->buf_start
= buf
->buf_used
= 0;
16 memset(buf
->buf
, 0, sz
);
22 void buf_rebase(buf_t buf
) {
23 if (buf
->buf_start
== 0)
25 memmove(buf
->buf
, buf
->buf
+ buf
->buf_start
, buf
->buf_used
);
30 int buf_makeroom(buf_t
*pbuf
, size_t roomfor
) {
37 *pbuf
= buf_new(roomfor
);
45 if (BUF_ROOM(*pbuf
) >= roomfor
)
48 new_sz
= (*pbuf
)->buf_used
+ roomfor
;
49 tmp_ptr
= realloc(*pbuf
, new_sz
+ sizeof **pbuf
);
50 if (tmp_ptr
== NULL
) {
51 NOTIFY_ERROR("%s:%s", "realloc", strerror(errno
));
55 (*pbuf
)->buf_sz
= new_sz
;
61 int buf_range_dup_or_append(buf_t src
, size_t src_offset
, size_t n
, buf_t
*pdst
) {
64 assert(src_offset
+ n
<= src
->buf_used
);
66 if (buf_makeroom(pdst
, n
)) {
70 memcpy((*pdst
)->buf
+ (*pdst
)->buf_used
, src
->buf
+ src
->buf_start
+ src_offset
, n
);
71 (*pdst
)->buf_used
+= n
;
76 /* Room for improvement:
77 Depending on ratio of flensed portion to buffer use, try to do less
78 copying-around of buffer ranges, by swapping buf pointers instead.
80 ssize_t
buf_flense(buf_t
*psrc
, size_t src_offset
, int delimiter
, buf_t
*pdst
) {
81 const size_t delimiter_len
= 1;
85 assert(src_offset
<= (*psrc
)->buf_used
);
87 NOTIFY_DEBUG("src_offset:%zu", src_offset
);
89 D_BUF("dst ", pdst
? *pdst
: NULL
);
91 for (i
= src_offset
; i
< (*psrc
)->buf_used
; i
++) {
92 if ((*psrc
)->buf
[(*psrc
)->buf_start
+ i
] == delimiter
) {
95 if (buf_range_dup_or_append((*psrc
), 0, i
, pdst
)) {
100 (*psrc
)->buf_start
+= i
+ delimiter_len
;
101 (*psrc
)->buf_used
-= i
+ delimiter_len
;
103 D_BUF("src ", *psrc
);
104 D_BUF("dst ", pdst
? *pdst
: NULL
);
105 return i
+ delimiter_len
;
114 static const char buf_flense_testdata1_
[] = "a\nbc\ndef\nghij\nklmno\npqr\ns\ntuv\nwxyz0\n1234\n567\n89\n0leftovers";
115 static const char buf_flense_testdata2_
[] = "\n\nfoo\nbar\n\n";
117 struct buf_flense_expected_result_
{
120 } buf_flense_expected1
[] = {
134 }, buf_flense_expected2
[] = {
143 struct test_buf_flense_data_
{
145 const struct buf_flense_expected_result_
*expected
;
146 } test_buf_flense_data1
= {
147 .src
= buf_flense_testdata1_
,
148 .expected
= buf_flense_expected1
,
149 }, test_buf_flense_data2
= {
150 .src
= buf_flense_testdata2_
,
151 .expected
= buf_flense_expected2
,
155 int test_buf_flense_(void *test_arg
, void *suite_arg
) {
157 struct test_buf_flense_data_
*test_data
= (struct test_buf_flense_data_
*)test_arg
;
158 const char testdata_len
= strlen(test_data
->src
);
159 const struct buf_flense_expected_result_
*next_result
= test_data
->expected
;
163 TEST_INFO("initializing src buffer with %zu characters", testdata_len
);
164 src
= buf_new(testdata_len
);
166 TEST_ERROR("%s:%s", "new_buf_", "failed");
169 memcpy(src
->buf
, test_data
->src
, testdata_len
);
170 src
->buf_used
+= testdata_len
;
178 r
= buf_flense(&src
, 0, '\n', &dst
);
179 if (r
!= next_result
->r
) {
180 TEST_ERROR("result '%zd' does not match expected result '%zd'", r
, next_result
->r
);
184 TEST_INFO("finished flensing");
188 if (strlen(next_result
->buf
) > dst
->buf_used
) {
189 TEST_ERROR("flensed buffer smaller than expected result '%s'", next_result
->buf
);
192 } else if (memcmp(next_result
->buf
, dst
->buf
+ dst
->buf_start
, strlen(next_result
->buf
))) {
193 TEST_ERROR("flensed buffer does not match expected result '%s'", next_result
->buf
);
198 TEST_INFO("flensed: '%.*s'", (int)dst
->buf_used
, dst
->buf
+ dst
->buf_start
);
200 memset(dst
, 0, dst
->buf_sz
+ sizeof *dst
);
206 if (strlen(next_result
->buf
) > src
->buf_used
) {
207 TEST_ERROR("remaining buffer smaller than expected result '%s'", next_result
->buf
);
210 } else if (memcmp(next_result
->buf
, src
->buf
+ src
->buf_start
, strlen(next_result
->buf
))) {
211 TEST_ERROR("remaining buffer does not match expected result '%s'", next_result
->buf
);
216 TEST_INFO("remains: '%.*s'", (int)src
->buf_used
, src
->buf
+ src
->buf_start
);
218 memset(src
, 0, src
->buf_sz
+ sizeof *src
);
225 void *test_suite_data
;
227 int test_suite_pre(void *suite_data
) {
232 int test_suite_post(void *suite_data
) {
237 test_t test_suite
[] = {
238 { "test_buf_flense_ 1", test_buf_flense_
, NULL
, NULL
, &test_buf_flense_data1
},
239 { "test_buf_flense_ 2", test_buf_flense_
, NULL
, NULL
, &test_buf_flense_data2
},
240 { NULL
, NULL
, NULL
, NULL
, NULL
},