summaryrefslogtreecommitdiff
path: root/snappy.cc
diff options
context:
space:
mode:
authorMatt Callanan <mpcallanan@google.com>2022-09-26 10:23:33 -0700
committerVictor Costan <costan@google.com>2022-09-29 09:32:28 -0700
commit9758c9dfd744f252bf3351c1a212e05c9f7fc857 (patch)
tree3dc9b0855cbae727ec38424c42a47a46c90b9a2b /snappy.cc
parentaf720f9a3b2c831f173b6074961737516f2d3a46 (diff)
downloadsnappy-git-9758c9dfd744f252bf3351c1a212e05c9f7fc857.tar.gz
Add `snappy::CompressFromIOVec`.
This reads from an `iovec` array rather than from a `char` array as in `snappy::Compress`. PiperOrigin-RevId: 476930623
Diffstat (limited to 'snappy.cc')
-rw-r--r--snappy.cc92
1 files changed, 91 insertions, 1 deletions
diff --git a/snappy.cc b/snappy.cc
index 6502cfd..5457377 100644
--- a/snappy.cc
+++ b/snappy.cc
@@ -1580,6 +1580,67 @@ size_t Compress(Source* reader, Sink* writer) {
// IOVec interfaces
// -----------------------------------------------------------------------
+// A `Source` implementation that yields the contents of an `iovec` array. Note
+// that `total_size` is the total number of bytes to be read from the elements
+// of `iov` (_not_ the total number of elements in `iov`).
+class SnappyIOVecReader : public Source {
+ public:
+ SnappyIOVecReader(const struct iovec* iov, size_t total_size)
+ : curr_iov_(iov),
+ curr_pos_(total_size > 0 ? reinterpret_cast<const char*>(iov->iov_base)
+ : nullptr),
+ curr_size_remaining_(total_size > 0 ? iov->iov_len : 0),
+ total_size_remaining_(total_size) {
+ // Skip empty leading `iovec`s.
+ if (total_size > 0 && curr_size_remaining_ == 0) Advance();
+ }
+
+ ~SnappyIOVecReader() = default;
+
+ size_t Available() const { return total_size_remaining_; }
+
+ const char* Peek(size_t* len) {
+ *len = curr_size_remaining_;
+ return curr_pos_;
+ }
+
+ void Skip(size_t n) {
+ while (n >= curr_size_remaining_ && n > 0) {
+ n -= curr_size_remaining_;
+ Advance();
+ }
+ curr_size_remaining_ -= n;
+ total_size_remaining_ -= n;
+ curr_pos_ += n;
+ }
+
+ private:
+ // Advances to the next nonempty `iovec` and updates related variables.
+ void Advance() {
+ do {
+ assert(total_size_remaining_ >= curr_size_remaining_);
+ total_size_remaining_ -= curr_size_remaining_;
+ if (total_size_remaining_ == 0) {
+ curr_pos_ = nullptr;
+ curr_size_remaining_ = 0;
+ return;
+ }
+ ++curr_iov_;
+ curr_pos_ = reinterpret_cast<const char*>(curr_iov_->iov_base);
+ curr_size_remaining_ = curr_iov_->iov_len;
+ } while (curr_size_remaining_ == 0);
+ }
+
+ // The `iovec` currently being read.
+ const struct iovec* curr_iov_;
+ // The location in `curr_iov_` currently being read.
+ const char* curr_pos_;
+ // The amount of unread data in `curr_iov_`.
+ size_t curr_size_remaining_;
+ // The amount of unread data in the entire input array.
+ size_t total_size_remaining_;
+};
+
// A type that writes to an iovec.
// Note that this is not a "ByteSink", but a type that matches the
// Writer template argument to SnappyDecompressor::DecompressAllTags().
@@ -1954,6 +2015,16 @@ void RawCompress(const char* input, size_t input_length, char* compressed,
*compressed_length = (writer.CurrentDestination() - compressed);
}
+void RawCompressFromIOVec(const struct iovec* iov, size_t uncompressed_length,
+ char* compressed, size_t* compressed_length) {
+ SnappyIOVecReader reader(iov, uncompressed_length);
+ UncheckedByteArraySink writer(compressed);
+ Compress(&reader, &writer);
+
+ // Compute how many bytes were added.
+ *compressed_length = writer.CurrentDestination() - compressed;
+}
+
size_t Compress(const char* input, size_t input_length,
std::string* compressed) {
// Pre-grow the buffer to the max length of the compressed output
@@ -1962,7 +2033,26 @@ size_t Compress(const char* input, size_t input_length,
size_t compressed_length;
RawCompress(input, input_length, string_as_array(compressed),
&compressed_length);
- compressed->resize(compressed_length);
+ compressed->erase(compressed_length);
+ return compressed_length;
+}
+
+size_t CompressFromIOVec(const struct iovec* iov, size_t iov_cnt,
+ std::string* compressed) {
+ // Compute the number of bytes to be compressed.
+ size_t uncompressed_length = 0;
+ for (int i = 0; i < iov_cnt; ++i) {
+ uncompressed_length += iov[i].iov_len;
+ }
+
+ // Pre-grow the buffer to the max length of the compressed output.
+ STLStringResizeUninitialized(compressed, MaxCompressedLength(
+ uncompressed_length));
+
+ size_t compressed_length;
+ RawCompressFromIOVec(iov, uncompressed_length, string_as_array(compressed),
+ &compressed_length);
+ compressed->erase(compressed_length);
return compressed_length;
}