8 #include "test_suite.h"
10 /* If these ever need to be overridden... */
11 void *(*buf_malloc_
)(size_t) = malloc
;
12 void *(*buf_realloc_
)(void *, size_t) = realloc
;
13 void (*buf_free_
)(void *) = free
;
16 buf_t
buf_new(size_t sz
) {
17 buf_t buf
= buf_malloc_(sz
+ sizeof *buf
);
20 buf
->buf_start
= buf
->buf_used
= 0;
21 memset(buf
->buf
, 0, sz
);
27 void buf_del(buf_t
*pbuf
) {
37 void buf_rebase(buf_t buf
) {
38 if (buf
->buf_start
== 0)
40 memmove(buf
->buf
, buf
->buf
+ buf
->buf_start
, buf
->buf_used
);
45 int buf_makeroom(buf_t
*pbuf
, size_t roomfor
) {
52 *pbuf
= buf_new(roomfor
);
60 if (BUF_ROOM(*pbuf
) >= roomfor
)
63 new_sz
= (*pbuf
)->buf_used
+ roomfor
;
64 tmp_ptr
= buf_realloc_(*pbuf
, new_sz
+ sizeof **pbuf
);
65 if (tmp_ptr
== NULL
) {
66 NOTIFY_ERROR("%s:%s", "realloc", strerror(errno
));
70 (*pbuf
)->buf_sz
= new_sz
;
76 int buf_range_dup_or_append(buf_t src
, size_t src_offset
, size_t n
, buf_t
*pdst
) {
79 assert(src_offset
+ n
<= src
->buf_used
);
81 if (buf_makeroom(pdst
, n
)) {
85 memcpy((*pdst
)->buf
+ (*pdst
)->buf_used
, src
->buf
+ src
->buf_start
+ src_offset
, n
);
86 (*pdst
)->buf_used
+= n
;
91 /* Room for improvement:
92 Depending on ratio of flensed portion to buffer use, try to do less
93 copying-around of buffer ranges, by swapping buf pointers instead.
95 ssize_t
buf_flense(buf_t
*psrc
, size_t src_offset
, int delimiter
, buf_t
*pdst
) {
96 const size_t delimiter_len
= 1;
100 assert(src_offset
<= (*psrc
)->buf_used
);
102 NOTIFY_DEBUG("src_offset:%zu", src_offset
);
103 D_BUF("src ", *psrc
);
104 D_BUF("dst ", pdst
? *pdst
: NULL
);
106 for (i
= src_offset
; i
< (*psrc
)->buf_used
; i
++) {
107 if ((*psrc
)->buf
[(*psrc
)->buf_start
+ i
] == delimiter
) {
110 if (buf_range_dup_or_append((*psrc
), 0, i
, pdst
)) {
115 (*psrc
)->buf_start
+= i
+ delimiter_len
;
116 (*psrc
)->buf_used
-= i
+ delimiter_len
;
118 D_BUF("src ", *psrc
);
119 D_BUF("dst ", pdst
? *pdst
: NULL
);
120 return i
+ delimiter_len
;
129 static const char buf_flense_testdata1_
[] = "a\nbc\ndef\nghij\nklmno\npqr\ns\ntuv\nwxyz0\n1234\n567\n89\n0leftovers";
130 static const char buf_flense_testdata2_
[] = "\n\nfoo\nbar\n\n";
132 struct buf_flense_expected_result_
{
135 } buf_flense_expected1
[] = {
149 }, buf_flense_expected2
[] = {
158 struct test_buf_flense_data_
{
160 const struct buf_flense_expected_result_
*expected
;
161 } test_buf_flense_data1
= {
162 .src
= buf_flense_testdata1_
,
163 .expected
= buf_flense_expected1
,
164 }, test_buf_flense_data2
= {
165 .src
= buf_flense_testdata2_
,
166 .expected
= buf_flense_expected2
,
170 int test_buf_flense_(void *test_arg
, void *suite_arg
) {
172 struct test_buf_flense_data_
*test_data
= (struct test_buf_flense_data_
*)test_arg
;
173 const char testdata_len
= strlen(test_data
->src
);
174 const struct buf_flense_expected_result_
*next_result
= test_data
->expected
;
178 TEST_INFO("initializing src buffer with %zu characters", testdata_len
);
179 src
= buf_new(testdata_len
);
181 TEST_ERROR("%s:%s", "new_buf_", "failed");
184 memcpy(src
->buf
, test_data
->src
, testdata_len
);
185 src
->buf_used
+= testdata_len
;
193 r
= buf_flense(&src
, 0, '\n', &dst
);
194 if (r
!= next_result
->r
) {
195 TEST_ERROR("result '%zd' does not match expected result '%zd'", r
, next_result
->r
);
199 TEST_INFO("finished flensing");
203 if (strlen(next_result
->buf
) > dst
->buf_used
) {
204 TEST_ERROR("flensed buffer smaller than expected result '%s'", next_result
->buf
);
207 } else if (memcmp(next_result
->buf
, dst
->buf
+ dst
->buf_start
, strlen(next_result
->buf
))) {
208 TEST_ERROR("flensed buffer does not match expected result '%s'", next_result
->buf
);
213 TEST_INFO("flensed: '%.*s'", (int)dst
->buf_used
, dst
->buf
+ dst
->buf_start
);
215 memset(dst
, 0, dst
->buf_sz
+ sizeof *dst
);
220 if (strlen(next_result
->buf
) > src
->buf_used
) {
221 TEST_ERROR("remaining buffer smaller than expected result '%s'", next_result
->buf
);
224 } else if (memcmp(next_result
->buf
, src
->buf
+ src
->buf_start
, strlen(next_result
->buf
))) {
225 TEST_ERROR("remaining buffer does not match expected result '%s'", next_result
->buf
);
230 TEST_INFO("remains: '%.*s'", (int)src
->buf_used
, src
->buf
+ src
->buf_start
);
232 memset(src
, 0, src
->buf_sz
+ sizeof *src
);
238 void *test_suite_data
;
240 int test_suite_pre(void *suite_data
) {
245 int test_suite_post(void *suite_data
) {
250 test_t test_suite
[] = {
251 { "test_buf_flense_ 1", test_buf_flense_
, NULL
, NULL
, &test_buf_flense_data1
},
252 { "test_buf_flense_ 2", test_buf_flense_
, NULL
, NULL
, &test_buf_flense_data2
},
253 { NULL
, NULL
, NULL
, NULL
, NULL
},