diff --git a/core/containers/msg_buffer.cpp b/core/containers/msg_buffer.cpp new file mode 100644 index 0000000..eb8fd32 --- /dev/null +++ b/core/containers/msg_buffer.cpp @@ -0,0 +1,200 @@ +/** + * + * MsgBuffer.cc + * An Tao + * + * Public header file in trantor lib. + * + * Copyright 2018, An Tao. All rights reserved. + * Use of this source code is governed by a BSD-style license + * that can be found in the License file. + * + * + */ + +#include "msg_buffer.h" + +#include +#include "core/math/math.h" +#ifndef _WIN32 +#include +#include +#else +#include +#include +#endif +#include +#include + +using namespace trantor; +namespace trantor { +static constexpr size_t kBufferOffset{ 8 }; +} + +MsgBuffer::MsgBuffer(size_t len) : + head_(kBufferOffset), initCap_(len), buffer_(len + head_), tail_(head_) { +} + +void MsgBuffer::ensureWritableBytes(size_t len) { + if (writableBytes() >= len) + return; + if (head_ + writableBytes() >= + (len + kBufferOffset)) // move readable bytes + { + std::copy(begin() + head_, begin() + tail_, begin() + kBufferOffset); + tail_ = kBufferOffset + (tail_ - head_); + head_ = kBufferOffset; + return; + } + // create new buffer + size_t newLen; + if ((buffer_.size() * 2) > (kBufferOffset + readableBytes() + len)) + newLen = buffer_.size() * 2; + else + newLen = kBufferOffset + readableBytes() + len; + MsgBuffer newbuffer(newLen); + newbuffer.append(*this); + swap(newbuffer); +} +void MsgBuffer::swap(MsgBuffer &buf) noexcept { + buffer_.swap(buf.buffer_); + std::swap(head_, buf.head_); + std::swap(tail_, buf.tail_); + std::swap(initCap_, buf.initCap_); +} +void MsgBuffer::append(const MsgBuffer &buf) { + ensureWritableBytes(buf.readableBytes()); + memcpy(&buffer_[tail_], buf.peek(), buf.readableBytes()); + tail_ += buf.readableBytes(); +} +void MsgBuffer::append(const char *buf, size_t len) { + ensureWritableBytes(len); + memcpy(&buffer_[tail_], buf, len); + tail_ += len; +} +void MsgBuffer::appendInt16(const uint16_t s) { + uint16_t ss = htons(s); + append(static_cast((void *)&ss), 2); +} +void MsgBuffer::appendInt32(const uint32_t i) { + uint32_t ii = htonl(i); + append(static_cast((void *)&ii), 4); +} +void MsgBuffer::appendInt64(const uint64_t l) { + uint64_t ll = Math::hton64(l); + append(static_cast((void *)&ll), 8); +} + +void MsgBuffer::addInFrontInt16(const uint16_t s) { + uint16_t ss = htons(s); + addInFront(static_cast((void *)&ss), 2); +} +void MsgBuffer::addInFrontInt32(const uint32_t i) { + uint32_t ii = htonl(i); + addInFront(static_cast((void *)&ii), 4); +} +void MsgBuffer::addInFrontInt64(const uint64_t l) { + uint64_t ll = Math::hton64(l); + addInFront(static_cast((void *)&ll), 8); +} + +uint16_t MsgBuffer::peekInt16() const { + assert(readableBytes() >= 2); + uint16_t rs = *(static_cast((void *)peek())); + return ntohs(rs); +} +uint32_t MsgBuffer::peekInt32() const { + assert(readableBytes() >= 4); + uint32_t rl = *(static_cast((void *)peek())); + return ntohl(rl); +} +uint64_t MsgBuffer::peekInt64() const { + assert(readableBytes() >= 8); + uint64_t rll = *(static_cast((void *)peek())); + return Math::ntoh64(rll); +} + +void MsgBuffer::retrieve(size_t len) { + if (len >= readableBytes()) { + retrieveAll(); + return; + } + head_ += len; +} +void MsgBuffer::retrieveAll() { + if (buffer_.size() > (initCap_ * 2)) { + buffer_.resize(initCap_); + } + tail_ = head_ = kBufferOffset; +} +ssize_t MsgBuffer::readFd(int fd, int *retErrno) { + char extBuffer[8192]; + struct iovec vec[2]; + size_t writable = writableBytes(); + vec[0].iov_base = begin() + tail_; + vec[0].iov_len = static_cast(writable); + vec[1].iov_base = extBuffer; + vec[1].iov_len = sizeof(extBuffer); + const int iovcnt = (writable < sizeof extBuffer) ? 2 : 1; + ssize_t n = ::readv(fd, vec, iovcnt); + if (n < 0) { + *retErrno = errno; + } else if (static_cast(n) <= writable) { + tail_ += n; + } else { + tail_ = buffer_.size(); + append(extBuffer, n - writable); + } + return n; +} + +std::string MsgBuffer::read(size_t len) { + if (len > readableBytes()) + len = readableBytes(); + std::string ret(peek(), len); + retrieve(len); + return ret; +} +uint8_t MsgBuffer::readInt8() { + uint8_t ret = peekInt8(); + retrieve(1); + return ret; +} +uint16_t MsgBuffer::readInt16() { + uint16_t ret = peekInt16(); + retrieve(2); + return ret; +} +uint32_t MsgBuffer::readInt32() { + uint32_t ret = peekInt32(); + retrieve(4); + return ret; +} +uint64_t MsgBuffer::readInt64() { + uint64_t ret = peekInt64(); + retrieve(8); + return ret; +} + +void MsgBuffer::addInFront(const char *buf, size_t len) { + if (head_ >= len) { + memcpy(begin() + head_ - len, buf, len); + head_ -= len; + return; + } + if (len <= writableBytes()) { + std::copy(begin() + head_, begin() + tail_, begin() + head_ + len); + memcpy(begin() + head_, buf, len); + tail_ += len; + return; + } + size_t newLen; + if (len + readableBytes() < initCap_) + newLen = initCap_; + else + newLen = len + readableBytes(); + MsgBuffer newBuf(newLen); + newBuf.append(buf, len); + newBuf.append(*this); + swap(newBuf); +} diff --git a/web_backends/drogon/trantor/utils/MsgBuffer.h b/core/containers/msg_buffer.h similarity index 100% rename from web_backends/drogon/trantor/utils/MsgBuffer.h rename to core/containers/msg_buffer.h diff --git a/web_backends/drogon/drogon/lib/inc/drogon/HttpViewData.h b/web_backends/drogon/drogon/lib/inc/drogon/HttpViewData.h index ca2525f..1e678b2 100644 --- a/web_backends/drogon/drogon/lib/inc/drogon/HttpViewData.h +++ b/web_backends/drogon/drogon/lib/inc/drogon/HttpViewData.h @@ -20,7 +20,7 @@ #include #include #include -#include +#include "core/containers/msg_buffer.h" #include #include #include diff --git a/web_backends/drogon/drogon/lib/inc/http/HttpRequestImpl.h b/web_backends/drogon/drogon/lib/inc/http/HttpRequestImpl.h index 6d3f63d..f167c54 100644 --- a/web_backends/drogon/drogon/lib/inc/http/HttpRequestImpl.h +++ b/web_backends/drogon/drogon/lib/inc/http/HttpRequestImpl.h @@ -23,7 +23,7 @@ #include #include "core/net/inet_address.h" #include -#include +#include "core/containers/msg_buffer.h" #include #include #include diff --git a/web_backends/drogon/drogon/lib/inc/http/HttpRequestParser.cc b/web_backends/drogon/drogon/lib/inc/http/HttpRequestParser.cc index 8809039..6214284 100644 --- a/web_backends/drogon/drogon/lib/inc/http/HttpRequestParser.cc +++ b/web_backends/drogon/drogon/lib/inc/http/HttpRequestParser.cc @@ -19,7 +19,7 @@ #include "HttpUtils.h" #include #include -#include +#include "core/containers/msg_buffer.h" #include using namespace trantor; diff --git a/web_backends/drogon/drogon/lib/inc/http/HttpRequestParser.h b/web_backends/drogon/drogon/lib/inc/http/HttpRequestParser.h index a682191..dd56745 100644 --- a/web_backends/drogon/drogon/lib/inc/http/HttpRequestParser.h +++ b/web_backends/drogon/drogon/lib/inc/http/HttpRequestParser.h @@ -17,7 +17,7 @@ #include "../src/impl_forwards.h" #include #include -#include +#include "core/containers/msg_buffer.h" #include #include #include diff --git a/web_backends/drogon/drogon/lib/inc/http/HttpResponseImpl.h b/web_backends/drogon/drogon/lib/inc/http/HttpResponseImpl.h index b48ca1d..22fd499 100644 --- a/web_backends/drogon/drogon/lib/inc/http/HttpResponseImpl.h +++ b/web_backends/drogon/drogon/lib/inc/http/HttpResponseImpl.h @@ -21,7 +21,7 @@ #include #include "core/net/inet_address.h" #include "core/math/date.h" -#include +#include "core/containers/msg_buffer.h" #include #include #include diff --git a/web_backends/drogon/drogon/lib/inc/http/HttpResponseParser.cc b/web_backends/drogon/drogon/lib/inc/http/HttpResponseParser.cc index 75d6a83..3e183cc 100644 --- a/web_backends/drogon/drogon/lib/inc/http/HttpResponseParser.cc +++ b/web_backends/drogon/drogon/lib/inc/http/HttpResponseParser.cc @@ -15,7 +15,7 @@ #include "HttpResponseParser.h" #include "HttpResponseImpl.h" #include -#include +#include "core/containers/msg_buffer.h" #include using namespace trantor; using namespace drogon; diff --git a/web_backends/drogon/drogon/lib/inc/http/HttpResponseParser.h b/web_backends/drogon/drogon/lib/inc/http/HttpResponseParser.h index cde089c..5abaec6 100644 --- a/web_backends/drogon/drogon/lib/inc/http/HttpResponseParser.h +++ b/web_backends/drogon/drogon/lib/inc/http/HttpResponseParser.h @@ -16,7 +16,7 @@ #include "../src/impl_forwards.h" #include -#include +#include "core/containers/msg_buffer.h" #include #include #include diff --git a/web_backends/drogon/drogon/lib/inc/http/HttpUtils.h b/web_backends/drogon/drogon/lib/inc/http/HttpUtils.h index 4e91e90..a0a4579 100644 --- a/web_backends/drogon/drogon/lib/inc/http/HttpUtils.h +++ b/web_backends/drogon/drogon/lib/inc/http/HttpUtils.h @@ -16,7 +16,7 @@ #include "HttpTypes.h" #include -#include +#include "core/containers/msg_buffer.h" #include namespace drogon { diff --git a/web_backends/drogon/drogon/lib/tests/unittests/MsgBufferTest.cc b/web_backends/drogon/drogon/lib/tests/unittests/MsgBufferTest.cc index 2b38fc5..be3da42 100644 --- a/web_backends/drogon/drogon/lib/tests/unittests/MsgBufferTest.cc +++ b/web_backends/drogon/drogon/lib/tests/unittests/MsgBufferTest.cc @@ -1,5 +1,5 @@ #include -#include +#include "core/containers/msg_buffer.h" #include #include diff --git a/web_backends/drogon/trantor/net/TcpConnection.h b/web_backends/drogon/trantor/net/TcpConnection.h index 353d8b2..004830f 100644 --- a/web_backends/drogon/trantor/net/TcpConnection.h +++ b/web_backends/drogon/trantor/net/TcpConnection.h @@ -17,7 +17,7 @@ #include #include "core/net/inet_address.h" #include -#include +#include "core/containers/msg_buffer.h" #include #include #include diff --git a/web_backends/drogon/trantor/unittests/MsgBufferUnittest.cc b/web_backends/drogon/trantor/unittests/MsgBufferUnittest.cc index 9addd2c..ff47db9 100644 --- a/web_backends/drogon/trantor/unittests/MsgBufferUnittest.cc +++ b/web_backends/drogon/trantor/unittests/MsgBufferUnittest.cc @@ -1,4 +1,4 @@ -#include +#include "core/containers/msg_buffer.h" #include #include #include diff --git a/web_backends/drogon/trantor/utils/MsgBuffer.cc b/web_backends/drogon/trantor/utils/MsgBuffer.cc index 0ae068b..f099473 100644 --- a/web_backends/drogon/trantor/utils/MsgBuffer.cc +++ b/web_backends/drogon/trantor/utils/MsgBuffer.cc @@ -13,7 +13,7 @@ */ #include -#include +#include "core/containers/msg_buffer.h" #include "core/math/math.h" #ifndef _WIN32 #include