diff options
Diffstat (limited to 'src/chunked.cc')
| -rw-r--r-- | src/chunked.cc | 44 |
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); +} + |
