aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib/deps/rpclib/include/rpc/msgpack/vrefbuffer.hpp
diff options
context:
space:
mode:
authorAndrej Rode <andrej.rode@ettus.com>2017-04-03 18:49:58 -0700
committerMartin Braun <martin.braun@ettus.com>2017-12-22 15:03:45 -0800
commit53795c74aead4e6021bc788b788f8ed5b4a0166d (patch)
tree45e4075f3d8ffdee7dff7c72dd665f5c5b0c746c /host/lib/deps/rpclib/include/rpc/msgpack/vrefbuffer.hpp
parent6a12add1560545438e1bebc05efbafd05aace4f9 (diff)
downloaduhd-53795c74aead4e6021bc788b788f8ed5b4a0166d.tar.gz
uhd-53795c74aead4e6021bc788b788f8ed5b4a0166d.tar.bz2
uhd-53795c74aead4e6021bc788b788f8ed5b4a0166d.zip
uhd: add cut-down rpclib source tree and import tool
Diffstat (limited to 'host/lib/deps/rpclib/include/rpc/msgpack/vrefbuffer.hpp')
-rw-r--r--host/lib/deps/rpclib/include/rpc/msgpack/vrefbuffer.hpp300
1 files changed, 300 insertions, 0 deletions
diff --git a/host/lib/deps/rpclib/include/rpc/msgpack/vrefbuffer.hpp b/host/lib/deps/rpclib/include/rpc/msgpack/vrefbuffer.hpp
new file mode 100644
index 000000000..1fde5013d
--- /dev/null
+++ b/host/lib/deps/rpclib/include/rpc/msgpack/vrefbuffer.hpp
@@ -0,0 +1,300 @@
+//
+// MessagePack for C++ zero-copy buffer implementation
+//
+// Copyright (C) 2008-2013 FURUHASHI Sadayuki and KONDO Takatoshi
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#ifndef MSGPACK_VREFBUFFER_HPP
+#define MSGPACK_VREFBUFFER_HPP
+
+#include "rpc/msgpack/versioning.hpp"
+
+#include <stdexcept>
+
+#ifndef MSGPACK_VREFBUFFER_REF_SIZE
+#define MSGPACK_VREFBUFFER_REF_SIZE 32
+#endif
+
+#ifndef MSGPACK_VREFBUFFER_CHUNK_SIZE
+#define MSGPACK_VREFBUFFER_CHUNK_SIZE 8192
+#endif
+
+#ifndef _WIN32
+#include <sys/uio.h>
+#else
+struct iovec {
+ void *iov_base;
+ size_t iov_len;
+};
+#endif
+
+namespace clmdep_msgpack {
+
+/// @cond
+MSGPACK_API_VERSION_NAMESPACE(v1) {
+/// @endcond
+
+namespace detail {
+ // int64, uint64, double
+ std::size_t const packer_max_buffer_size = 9;
+} // detail
+
+class vrefbuffer {
+private:
+ struct chunk {
+ chunk* next;
+ };
+ struct inner_buffer {
+ size_t free;
+ char* ptr;
+ chunk* head;
+ };
+public:
+ vrefbuffer(size_t ref_size = MSGPACK_VREFBUFFER_REF_SIZE,
+ size_t chunk_size = MSGPACK_VREFBUFFER_CHUNK_SIZE)
+ :m_ref_size(std::max(ref_size, detail::packer_max_buffer_size + 1)),
+ m_chunk_size(chunk_size)
+ {
+ size_t nfirst = (sizeof(iovec) < 72/2) ?
+ 72 / sizeof(iovec) : 8;
+
+ iovec* array = static_cast<iovec*>(::malloc(
+ sizeof(iovec) * nfirst));
+ if(!array) {
+ throw std::bad_alloc();
+ }
+
+ m_tail = array;
+ m_end = array + nfirst;
+ m_array = array;
+
+ chunk* c = static_cast<chunk*>(::malloc(sizeof(chunk) + chunk_size));
+ if(!c) {
+ ::free(array);
+ throw std::bad_alloc();
+ }
+ inner_buffer* const ib = &m_inner_buffer;
+
+ ib->free = chunk_size;
+ ib->ptr = reinterpret_cast<char*>(c) + sizeof(chunk);
+ ib->head = c;
+ c->next = nullptr;
+
+ }
+
+ ~vrefbuffer()
+ {
+ chunk* c = m_inner_buffer.head;
+ while(true) {
+ chunk* n = c->next;
+ ::free(c);
+ if(n != NULL) {
+ c = n;
+ } else {
+ break;
+ }
+ }
+ ::free(m_array);
+ }
+
+public:
+ void write(const char* buf, size_t len)
+ {
+ if(len < m_ref_size) {
+ append_copy(buf, len);
+ } else {
+ append_ref(buf, len);
+ }
+ }
+
+ void append_ref(const char* buf, size_t len)
+ {
+ if(m_tail == m_end) {
+ const size_t nused = m_tail - m_array;
+ const size_t nnext = nused * 2;
+
+ iovec* nvec = static_cast<iovec*>(::realloc(
+ m_array, sizeof(iovec)*nnext));
+ if(!nvec) {
+ throw std::bad_alloc();
+ }
+
+ m_array = nvec;
+ m_end = nvec + nnext;
+ m_tail = nvec + nused;
+ }
+
+ m_tail->iov_base = const_cast<char*>(buf);
+ m_tail->iov_len = len;
+ ++m_tail;
+ }
+
+ void append_copy(const char* buf, size_t len)
+ {
+ inner_buffer* const ib = &m_inner_buffer;
+
+ if(ib->free < len) {
+ size_t sz = m_chunk_size;
+ if(sz < len) {
+ sz = len;
+ }
+
+ chunk* c = static_cast<chunk*>(::malloc(sizeof(chunk) + sz));
+ if(!c) {
+ throw std::bad_alloc();
+ }
+
+ c->next = ib->head;
+ ib->head = c;
+ ib->free = sz;
+ ib->ptr = reinterpret_cast<char*>(c) + sizeof(chunk);
+ }
+
+ char* m = ib->ptr;
+ std::memcpy(m, buf, len);
+ ib->free -= len;
+ ib->ptr += len;
+
+ if(m_tail != m_array && m ==
+ static_cast<const char*>(
+ const_cast<const void *>((m_tail - 1)->iov_base)
+ ) + (m_tail - 1)->iov_len) {
+ (m_tail - 1)->iov_len += len;
+ return;
+ } else {
+ append_ref( m, len);
+ }
+ }
+
+ const struct iovec* vector() const
+ {
+ return m_array;
+ }
+
+ size_t vector_size() const
+ {
+ return m_tail - m_array;
+ }
+
+ void migrate(vrefbuffer* to)
+ {
+ size_t sz = m_chunk_size;
+
+ chunk* empty = static_cast<chunk*>(::malloc(sizeof(chunk) + sz));
+ if(!empty) {
+ throw std::bad_alloc();
+ }
+
+ empty->next = nullptr;
+
+ const size_t nused = m_tail - m_array;
+ if(to->m_tail + nused < m_end) {
+ const size_t tosize = to->m_tail - to->m_array;
+ const size_t reqsize = nused + tosize;
+ size_t nnext = (to->m_end - to->m_array) * 2;
+ while(nnext < reqsize) {
+ size_t tmp_nnext = nnext * 2;
+ if (tmp_nnext <= nnext) {
+ nnext = reqsize;
+ break;
+ }
+ nnext = tmp_nnext;
+ }
+
+ iovec* nvec = static_cast<iovec*>(::realloc(
+ to->m_array, sizeof(iovec)*nnext));
+ if(!nvec) {
+ ::free(empty);
+ throw std::bad_alloc();
+ }
+
+ to->m_array = nvec;
+ to->m_end = nvec + nnext;
+ to->m_tail = nvec + tosize;
+ }
+
+ std::memcpy(to->m_tail, m_array, sizeof(iovec)*nused);
+
+ to->m_tail += nused;
+ m_tail = m_array;
+
+
+ inner_buffer* const ib = &m_inner_buffer;
+ inner_buffer* const toib = &to->m_inner_buffer;
+
+ chunk* last = ib->head;
+ while(last->next) {
+ last = last->next;
+ }
+ last->next = toib->head;
+ toib->head = ib->head;
+
+ if(toib->free < ib->free) {
+ toib->free = ib->free;
+ toib->ptr = ib->ptr;
+ }
+
+ ib->head = empty;
+ ib->free = sz;
+ ib->ptr = reinterpret_cast<char*>(empty) + sizeof(chunk);
+
+ }
+
+ void clear()
+ {
+ chunk* c = m_inner_buffer.head->next;
+ chunk* n;
+ while(c) {
+ n = c->next;
+ ::free(c);
+ c = n;
+ }
+
+ inner_buffer* const ib = &m_inner_buffer;
+ c = ib->head;
+ c->next = nullptr;
+ ib->free = m_chunk_size;
+ ib->ptr = reinterpret_cast<char*>(c) + sizeof(chunk);
+
+ m_tail = m_array;
+ }
+
+#if defined(MSGPACK_USE_CPP03)
+private:
+ vrefbuffer(const vrefbuffer&);
+ vrefbuffer& operator=(const vrefbuffer&);
+#else // defined(MSGPACK_USE_CPP03)
+ vrefbuffer(const vrefbuffer&) = delete;
+ vrefbuffer& operator=(const vrefbuffer&) = delete;
+#endif // defined(MSGPACK_USE_CPP03)
+
+private:
+ iovec* m_tail;
+ iovec* m_end;
+ iovec* m_array;
+
+ size_t m_ref_size;
+ size_t m_chunk_size;
+
+ inner_buffer m_inner_buffer;
+
+};
+
+/// @cond
+} // MSGPACK_API_VERSION_NAMESPACE(v1)
+/// @endcond
+
+} // namespace clmdep_msgpack
+
+#endif /* msgpack/vrefbuffer.hpp */