summaryrefslogtreecommitdiff
path: root/src/chunked.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/chunked.cc')
-rw-r--r--src/chunked.cc44
1 files changed, 42 insertions, 2 deletions
diff --git a/src/chunked.cc b/src/chunked.cc
index 99aea0d..dfafd89 100644
--- a/src/chunked.cc
+++ b/src/chunked.cc
@@ -13,6 +13,7 @@ namespace {
enum State {
CHUNK,
IN_CHUNK,
+ END_CHUNK,
TRAILER,
DONE,
};
@@ -51,13 +52,29 @@ public:
}
break;
}
- case IN_CHUNK:
- if (static_cast<uint64_t>(end - d) < size_) {
+ case IN_CHUNK: {
+ uint64_t left = end - d;
+ if (left < size_) {
+ this->data(d, left);
+ size_ -= left;
return avail;
}
+ this->data(d, size_);
d += size_;
+ state_ = END_CHUNK;
+ break;
+ }
+ case END_CHUNK: {
+ auto p = find_crlf(d, end);
+ if (!p) return d - start;
+ if (p != d) {
+ good_ = false;
+ return d - start;
+ }
+ d = p + 2;
state_ = CHUNK;
break;
+ }
case TRAILER: {
auto p = find_crlf(d, end);
if (!p) return d - start;
@@ -81,6 +98,10 @@ public:
return state_ == DONE;
}
+protected:
+ virtual void data(void const* UNUSED(data), size_t UNUSED(size)) {
+ }
+
private:
char const* find_crlf(char const* start, char const* end) {
for (; start != end; ++start) {
@@ -97,6 +118,20 @@ private:
uint64_t size_;
};
+class ChunkedCallbackImpl : public ChunkedImpl {
+public:
+ ChunkedCallbackImpl(DataCallback const& callback)
+ : callback_(callback) {
+ }
+
+ void data(void const* data, size_t size) override {
+ callback_(data, size);
+ }
+
+private:
+ DataCallback const callback_;
+};
+
} // namespace
// static
@@ -104,3 +139,8 @@ Chunked* Chunked::create() {
return new ChunkedImpl();
}
+// static
+Chunked* Chunked::create(DataCallback const& callback) {
+ return new ChunkedCallbackImpl(callback);
+}
+