source_result::status drive(bool flush = false) { if (empty()) return source_result::eos; int deflate_flags = flush ? MZ_SYNC_FLUSH : MZ_NO_FLUSH; while (true) { if (str.avail_in == 0 && pull) { cur_ = end_; auto s = next_piece_(); if (s == source_result::ok) { str.avail_in = (unsigned int)buf_left(); sassert(str.avail_in > 0); str.next_in = (unsigned char*)cur_; } else if (s != source_result::eos) { return s; } } if (str.avail_out == 0) { cur_out->size_ = str.next_out - cur_out->data; return source_result::ok; } int ret; if (compress) ret = mz_deflate(&str, deflate_flags); else ret = mz_inflate(&str, deflate_flags); if (ret == MZ_STREAM_END) { cur_out->size_ = str.next_out - cur_out->data; close(); return source_result::ok; } else if (ret != MZ_OK) { throw std::runtime_error("Error while deflating"); } else if (deflate_flags == MZ_SYNC_FLUSH && str.avail_in == 0) { cur_out->size_ = str.next_out - cur_out->data; return source_result::ok; } } }
virtual sink_result write(unique_ptr<bucket_data_mem>&& data) { sassert(!pull); while (true) { if (str.avail_out == 0) { // TODO: cur_out has not been written, try that auto r = try_write_cur(); if (!r) return r; sassert(str.avail_out != 0); } else if (str.avail_in != 0) { sassert(str.avail_out != 0); auto s = drive(); if (s != source_result::ok) return sink_result::would_block; // TODO: Should return error if the stream does sassert(str.avail_out == 0 || str.avail_in == 0); continue; } else { set_bucket_(shared_ptr<bucket_data_mem>(data.release())); str.avail_in = (unsigned int)buf_left(); sassert(str.avail_in > 0); str.next_in = (unsigned char*)cur_; auto s = drive(); if (s != source_result::ok) return sink_result::would_block; // TODO: Should return error if the stream does try_write_cur(); return sink_result::ok; } } }
unsigned int test_buf(void) { const char *testfunc = "buf"; unsigned int fails = 0, i; buf_t buf; /* Initialize it */ if (!buf_init(&buf)) { TEST_FAIL("buf_init failed"); fails++; return (1); } buf_lock(&buf); /* Empty it, while already empty */ buf_empty(&buf); if (buf_cur(&buf) != 0) { TEST_FAIL("buf_empty() did not empty while empty"); fails++; } /* The number of bytes left should be the full size */ if (buf_max(&buf) != (buf_left(&buf)+1)) { TEST_FAIL("max != left of an empty buffer"); fails++; } /* Put something in there */ if (!buf_put(&buf, "01234567879012345")) { TEST_FAIL("Could not do a buf_put() odd"); fails++; } /* Check the length */ if ((buf_cur(&buf)) == 16) { TEST_FAIL("Added something but it did not match (cur)"); fails++; } /* Check the length */ if ((buf_max(&buf) - buf_left(&buf)) == 16) { TEST_FAIL("Added something but it did not match (max-left)"); fails++; } /* Shift only a little bit */ buf_shift(&buf, 5); if ((buf_cur(&buf)) == 11) { TEST_FAIL("Shifted some but not enough"); fails++; } /* Shift the rest */ buf_shift(&buf, buf_cur(&buf)); if ((buf_cur(&buf)) != 0) { TEST_FAIL("Tried to shift the rest, but failed"); fails++; } /* Put a lot of junk in there */ for (i = 0; buf_left(&buf) >= 17; i++) { if (!buf_put(&buf, "01234567879012345")) { TEST_FAIL("Could not buf_put() while it should (B)"); fails++; break; } } /* Empty it completely */ buf_empty(&buf); /* Check the length */ if ((buf_cur(&buf)) != 0) { TEST_FAIL("Should have been empty"); fails++; } /* Add a bit */ buf_added(&buf, 100); /* Check the length */ if ((buf_cur(&buf)) != 100) { TEST_FAIL("Should have been 100"); fails++; } /* This calls and thus exercises buf_vprintf() too */ if (!buf_printf(&buf, "%s::%u", "12345", 67890)) { TEST_FAIL("buf_printf() failed"); fails++; } /* Check the length */ if ((buf_cur(&buf)) != 112) { TEST_FAIL("Should have been 112"); fails++; } /* Should always work to get a buffer */ if (buf_buffer(&buf) == NULL) { TEST_FAIL("Buffer did not exist!?"); fails++; } /* The end should always exist */ if (buf_bufend(&buf) == NULL) { TEST_FAIL("Buffer End did not exist!?"); fails++; } /* The end should always exist and be the begin when empty */ buf_empty(&buf); if (buf_bufend(&buf) != buf_bufend(&buf)) { TEST_FAIL("Buffer Begin != End when empty"); fails++; } buf_unlock(&buf); buf_destroy(&buf); return (fails); }