Hideaki Tai / msgpack-embedded

Dependents:   hello_message_pack

Committer:
hideakitai
Date:
Sat Feb 13 01:53:11 2016 +0000
Revision:
0:3f9dbf1e2cb0
Child:
3:a56553e46a9a
first commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
hideakitai 0:3f9dbf1e2cb0 1 //
hideakitai 0:3f9dbf1e2cb0 2 // MessagePack for C++ zero-copy buffer implementation
hideakitai 0:3f9dbf1e2cb0 3 //
hideakitai 0:3f9dbf1e2cb0 4 // Copyright (C) 2008-2013 FURUHASHI Sadayuki and KONDO Takatoshi
hideakitai 0:3f9dbf1e2cb0 5 //
hideakitai 0:3f9dbf1e2cb0 6 // Distributed under the Boost Software License, Version 1.0.
hideakitai 0:3f9dbf1e2cb0 7 // (See accompanying file LICENSE_1_0.txt or copy at
hideakitai 0:3f9dbf1e2cb0 8 // http://www.boost.org/LICENSE_1_0.txt)
hideakitai 0:3f9dbf1e2cb0 9 //
hideakitai 0:3f9dbf1e2cb0 10 #ifndef MSGPACK_VREFBUFFER_HPP
hideakitai 0:3f9dbf1e2cb0 11 #define MSGPACK_VREFBUFFER_HPP
hideakitai 0:3f9dbf1e2cb0 12
hideakitai 0:3f9dbf1e2cb0 13 #include "msgpack/versioning.hpp"
hideakitai 0:3f9dbf1e2cb0 14
hideakitai 0:3f9dbf1e2cb0 15 #include <stdexcept>
hideakitai 0:3f9dbf1e2cb0 16
hideakitai 0:3f9dbf1e2cb0 17 #ifndef MSGPACK_VREFBUFFER_REF_SIZE
hideakitai 0:3f9dbf1e2cb0 18 #define MSGPACK_VREFBUFFER_REF_SIZE 32
hideakitai 0:3f9dbf1e2cb0 19 #endif
hideakitai 0:3f9dbf1e2cb0 20
hideakitai 0:3f9dbf1e2cb0 21 #ifndef MSGPACK_VREFBUFFER_CHUNK_SIZE
hideakitai 0:3f9dbf1e2cb0 22 #if defined(__MBED__)
hideakitai 0:3f9dbf1e2cb0 23 #define MSGPACK_VREFBUFFER_CHUNK_SIZE 1024
hideakitai 0:3f9dbf1e2cb0 24 #elif defined(__AVR__)
hideakitai 0:3f9dbf1e2cb0 25 #define MSGPACK_VREFBUFFER_CHUNK_SIZE 128
hideakitai 0:3f9dbf1e2cb0 26 #else
hideakitai 0:3f9dbf1e2cb0 27 #define MSGPACK_VREFBUFFER_CHUNK_SIZE 8192
hideakitai 0:3f9dbf1e2cb0 28 #endif
hideakitai 0:3f9dbf1e2cb0 29 #endif
hideakitai 0:3f9dbf1e2cb0 30
hideakitai 0:3f9dbf1e2cb0 31 #if !defined(_WIN32) && !defined(__MBED__)
hideakitai 0:3f9dbf1e2cb0 32 #include <sys/uio.h>
hideakitai 0:3f9dbf1e2cb0 33 #else
hideakitai 0:3f9dbf1e2cb0 34 struct iovec {
hideakitai 0:3f9dbf1e2cb0 35 void *iov_base;
hideakitai 0:3f9dbf1e2cb0 36 size_t iov_len;
hideakitai 0:3f9dbf1e2cb0 37 };
hideakitai 0:3f9dbf1e2cb0 38 #endif
hideakitai 0:3f9dbf1e2cb0 39
hideakitai 0:3f9dbf1e2cb0 40 namespace msgpack {
hideakitai 0:3f9dbf1e2cb0 41
hideakitai 0:3f9dbf1e2cb0 42 /// @cond
hideakitai 0:3f9dbf1e2cb0 43 MSGPACK_API_VERSION_NAMESPACE(v1) {
hideakitai 0:3f9dbf1e2cb0 44 /// @endcond
hideakitai 0:3f9dbf1e2cb0 45
hideakitai 0:3f9dbf1e2cb0 46 namespace detail {
hideakitai 0:3f9dbf1e2cb0 47 // int64, uint64, double
hideakitai 0:3f9dbf1e2cb0 48 std::size_t const packer_max_buffer_size = 9;
hideakitai 0:3f9dbf1e2cb0 49 } // detail
hideakitai 0:3f9dbf1e2cb0 50
hideakitai 0:3f9dbf1e2cb0 51 class vrefbuffer {
hideakitai 0:3f9dbf1e2cb0 52 private:
hideakitai 0:3f9dbf1e2cb0 53 struct chunk {
hideakitai 0:3f9dbf1e2cb0 54 chunk* next;
hideakitai 0:3f9dbf1e2cb0 55 };
hideakitai 0:3f9dbf1e2cb0 56 struct inner_buffer {
hideakitai 0:3f9dbf1e2cb0 57 size_t free;
hideakitai 0:3f9dbf1e2cb0 58 char* ptr;
hideakitai 0:3f9dbf1e2cb0 59 chunk* head;
hideakitai 0:3f9dbf1e2cb0 60 };
hideakitai 0:3f9dbf1e2cb0 61 public:
hideakitai 0:3f9dbf1e2cb0 62 vrefbuffer(size_t ref_size = MSGPACK_VREFBUFFER_REF_SIZE,
hideakitai 0:3f9dbf1e2cb0 63 size_t chunk_size = MSGPACK_VREFBUFFER_CHUNK_SIZE)
hideakitai 0:3f9dbf1e2cb0 64 :m_ref_size(std::max(ref_size, detail::packer_max_buffer_size + 1)),
hideakitai 0:3f9dbf1e2cb0 65 m_chunk_size(chunk_size)
hideakitai 0:3f9dbf1e2cb0 66 {
hideakitai 0:3f9dbf1e2cb0 67 size_t nfirst = (sizeof(iovec) < 72/2) ?
hideakitai 0:3f9dbf1e2cb0 68 72 / sizeof(iovec) : 8;
hideakitai 0:3f9dbf1e2cb0 69
hideakitai 0:3f9dbf1e2cb0 70 iovec* array = static_cast<iovec*>(::malloc(
hideakitai 0:3f9dbf1e2cb0 71 sizeof(iovec) * nfirst));
hideakitai 0:3f9dbf1e2cb0 72 if(!array) {
hideakitai 0:3f9dbf1e2cb0 73 // throw std::bad_alloc();
hideakitai 0:3f9dbf1e2cb0 74 }
hideakitai 0:3f9dbf1e2cb0 75
hideakitai 0:3f9dbf1e2cb0 76 m_tail = array;
hideakitai 0:3f9dbf1e2cb0 77 m_end = array + nfirst;
hideakitai 0:3f9dbf1e2cb0 78 m_array = array;
hideakitai 0:3f9dbf1e2cb0 79
hideakitai 0:3f9dbf1e2cb0 80 chunk* c = static_cast<chunk*>(::malloc(sizeof(chunk) + chunk_size));
hideakitai 0:3f9dbf1e2cb0 81 if(!c) {
hideakitai 0:3f9dbf1e2cb0 82 ::free(array);
hideakitai 0:3f9dbf1e2cb0 83 // throw std::bad_alloc();
hideakitai 0:3f9dbf1e2cb0 84 }
hideakitai 0:3f9dbf1e2cb0 85 inner_buffer* const ib = &m_inner_buffer;
hideakitai 0:3f9dbf1e2cb0 86
hideakitai 0:3f9dbf1e2cb0 87 ib->free = chunk_size;
hideakitai 0:3f9dbf1e2cb0 88 ib->ptr = reinterpret_cast<char*>(c) + sizeof(chunk);
hideakitai 0:3f9dbf1e2cb0 89 ib->head = c;
hideakitai 0:3f9dbf1e2cb0 90 c->next = nullptr;
hideakitai 0:3f9dbf1e2cb0 91
hideakitai 0:3f9dbf1e2cb0 92 }
hideakitai 0:3f9dbf1e2cb0 93
hideakitai 0:3f9dbf1e2cb0 94 ~vrefbuffer()
hideakitai 0:3f9dbf1e2cb0 95 {
hideakitai 0:3f9dbf1e2cb0 96 chunk* c = m_inner_buffer.head;
hideakitai 0:3f9dbf1e2cb0 97 while(true) {
hideakitai 0:3f9dbf1e2cb0 98 chunk* n = c->next;
hideakitai 0:3f9dbf1e2cb0 99 ::free(c);
hideakitai 0:3f9dbf1e2cb0 100 if(n != NULL) {
hideakitai 0:3f9dbf1e2cb0 101 c = n;
hideakitai 0:3f9dbf1e2cb0 102 } else {
hideakitai 0:3f9dbf1e2cb0 103 break;
hideakitai 0:3f9dbf1e2cb0 104 }
hideakitai 0:3f9dbf1e2cb0 105 }
hideakitai 0:3f9dbf1e2cb0 106 ::free(m_array);
hideakitai 0:3f9dbf1e2cb0 107 }
hideakitai 0:3f9dbf1e2cb0 108
hideakitai 0:3f9dbf1e2cb0 109 public:
hideakitai 0:3f9dbf1e2cb0 110 void write(const char* buf, size_t len)
hideakitai 0:3f9dbf1e2cb0 111 {
hideakitai 0:3f9dbf1e2cb0 112 if(len < m_ref_size) {
hideakitai 0:3f9dbf1e2cb0 113 append_copy(buf, len);
hideakitai 0:3f9dbf1e2cb0 114 } else {
hideakitai 0:3f9dbf1e2cb0 115 append_ref(buf, len);
hideakitai 0:3f9dbf1e2cb0 116 }
hideakitai 0:3f9dbf1e2cb0 117 }
hideakitai 0:3f9dbf1e2cb0 118
hideakitai 0:3f9dbf1e2cb0 119 void append_ref(const char* buf, size_t len)
hideakitai 0:3f9dbf1e2cb0 120 {
hideakitai 0:3f9dbf1e2cb0 121 if(m_tail == m_end) {
hideakitai 0:3f9dbf1e2cb0 122 const size_t nused = m_tail - m_array;
hideakitai 0:3f9dbf1e2cb0 123 const size_t nnext = nused * 2;
hideakitai 0:3f9dbf1e2cb0 124
hideakitai 0:3f9dbf1e2cb0 125 iovec* nvec = static_cast<iovec*>(::realloc(
hideakitai 0:3f9dbf1e2cb0 126 m_array, sizeof(iovec)*nnext));
hideakitai 0:3f9dbf1e2cb0 127 if(!nvec) {
hideakitai 0:3f9dbf1e2cb0 128 // throw std::bad_alloc();
hideakitai 0:3f9dbf1e2cb0 129 }
hideakitai 0:3f9dbf1e2cb0 130
hideakitai 0:3f9dbf1e2cb0 131 m_array = nvec;
hideakitai 0:3f9dbf1e2cb0 132 m_end = nvec + nnext;
hideakitai 0:3f9dbf1e2cb0 133 m_tail = nvec + nused;
hideakitai 0:3f9dbf1e2cb0 134 }
hideakitai 0:3f9dbf1e2cb0 135
hideakitai 0:3f9dbf1e2cb0 136 m_tail->iov_base = const_cast<char*>(buf);
hideakitai 0:3f9dbf1e2cb0 137 m_tail->iov_len = len;
hideakitai 0:3f9dbf1e2cb0 138 ++m_tail;
hideakitai 0:3f9dbf1e2cb0 139 }
hideakitai 0:3f9dbf1e2cb0 140
hideakitai 0:3f9dbf1e2cb0 141 void append_copy(const char* buf, size_t len)
hideakitai 0:3f9dbf1e2cb0 142 {
hideakitai 0:3f9dbf1e2cb0 143 inner_buffer* const ib = &m_inner_buffer;
hideakitai 0:3f9dbf1e2cb0 144
hideakitai 0:3f9dbf1e2cb0 145 if(ib->free < len) {
hideakitai 0:3f9dbf1e2cb0 146 size_t sz = m_chunk_size;
hideakitai 0:3f9dbf1e2cb0 147 if(sz < len) {
hideakitai 0:3f9dbf1e2cb0 148 sz = len;
hideakitai 0:3f9dbf1e2cb0 149 }
hideakitai 0:3f9dbf1e2cb0 150
hideakitai 0:3f9dbf1e2cb0 151 chunk* c = static_cast<chunk*>(::malloc(sizeof(chunk) + sz));
hideakitai 0:3f9dbf1e2cb0 152 if(!c) {
hideakitai 0:3f9dbf1e2cb0 153 // throw std::bad_alloc();
hideakitai 0:3f9dbf1e2cb0 154 }
hideakitai 0:3f9dbf1e2cb0 155
hideakitai 0:3f9dbf1e2cb0 156 c->next = ib->head;
hideakitai 0:3f9dbf1e2cb0 157 ib->head = c;
hideakitai 0:3f9dbf1e2cb0 158 ib->free = sz;
hideakitai 0:3f9dbf1e2cb0 159 ib->ptr = reinterpret_cast<char*>(c) + sizeof(chunk);
hideakitai 0:3f9dbf1e2cb0 160 }
hideakitai 0:3f9dbf1e2cb0 161
hideakitai 0:3f9dbf1e2cb0 162 char* m = ib->ptr;
hideakitai 0:3f9dbf1e2cb0 163 std::memcpy(m, buf, len);
hideakitai 0:3f9dbf1e2cb0 164 ib->free -= len;
hideakitai 0:3f9dbf1e2cb0 165 ib->ptr += len;
hideakitai 0:3f9dbf1e2cb0 166
hideakitai 0:3f9dbf1e2cb0 167 if(m_tail != m_array && m ==
hideakitai 0:3f9dbf1e2cb0 168 static_cast<const char*>(
hideakitai 0:3f9dbf1e2cb0 169 const_cast<const void *>((m_tail - 1)->iov_base)
hideakitai 0:3f9dbf1e2cb0 170 ) + (m_tail - 1)->iov_len) {
hideakitai 0:3f9dbf1e2cb0 171 (m_tail - 1)->iov_len += len;
hideakitai 0:3f9dbf1e2cb0 172 return;
hideakitai 0:3f9dbf1e2cb0 173 } else {
hideakitai 0:3f9dbf1e2cb0 174 append_ref( m, len);
hideakitai 0:3f9dbf1e2cb0 175 }
hideakitai 0:3f9dbf1e2cb0 176 }
hideakitai 0:3f9dbf1e2cb0 177
hideakitai 0:3f9dbf1e2cb0 178 const struct iovec* vector() const
hideakitai 0:3f9dbf1e2cb0 179 {
hideakitai 0:3f9dbf1e2cb0 180 return m_array;
hideakitai 0:3f9dbf1e2cb0 181 }
hideakitai 0:3f9dbf1e2cb0 182
hideakitai 0:3f9dbf1e2cb0 183 size_t vector_size() const
hideakitai 0:3f9dbf1e2cb0 184 {
hideakitai 0:3f9dbf1e2cb0 185 return m_tail - m_array;
hideakitai 0:3f9dbf1e2cb0 186 }
hideakitai 0:3f9dbf1e2cb0 187
hideakitai 0:3f9dbf1e2cb0 188 void migrate(vrefbuffer* to)
hideakitai 0:3f9dbf1e2cb0 189 {
hideakitai 0:3f9dbf1e2cb0 190 size_t sz = m_chunk_size;
hideakitai 0:3f9dbf1e2cb0 191
hideakitai 0:3f9dbf1e2cb0 192 chunk* empty = static_cast<chunk*>(::malloc(sizeof(chunk) + sz));
hideakitai 0:3f9dbf1e2cb0 193 if(!empty) {
hideakitai 0:3f9dbf1e2cb0 194 // throw std::bad_alloc();
hideakitai 0:3f9dbf1e2cb0 195 }
hideakitai 0:3f9dbf1e2cb0 196
hideakitai 0:3f9dbf1e2cb0 197 empty->next = nullptr;
hideakitai 0:3f9dbf1e2cb0 198
hideakitai 0:3f9dbf1e2cb0 199 const size_t nused = m_tail - m_array;
hideakitai 0:3f9dbf1e2cb0 200 if(to->m_tail + nused < m_end) {
hideakitai 0:3f9dbf1e2cb0 201 const size_t tosize = to->m_tail - to->m_array;
hideakitai 0:3f9dbf1e2cb0 202 const size_t reqsize = nused + tosize;
hideakitai 0:3f9dbf1e2cb0 203 size_t nnext = (to->m_end - to->m_array) * 2;
hideakitai 0:3f9dbf1e2cb0 204 while(nnext < reqsize) {
hideakitai 0:3f9dbf1e2cb0 205 size_t tmp_nnext = nnext * 2;
hideakitai 0:3f9dbf1e2cb0 206 if (tmp_nnext <= nnext) {
hideakitai 0:3f9dbf1e2cb0 207 nnext = reqsize;
hideakitai 0:3f9dbf1e2cb0 208 break;
hideakitai 0:3f9dbf1e2cb0 209 }
hideakitai 0:3f9dbf1e2cb0 210 nnext = tmp_nnext;
hideakitai 0:3f9dbf1e2cb0 211 }
hideakitai 0:3f9dbf1e2cb0 212
hideakitai 0:3f9dbf1e2cb0 213 iovec* nvec = static_cast<iovec*>(::realloc(
hideakitai 0:3f9dbf1e2cb0 214 to->m_array, sizeof(iovec)*nnext));
hideakitai 0:3f9dbf1e2cb0 215 if(!nvec) {
hideakitai 0:3f9dbf1e2cb0 216 ::free(empty);
hideakitai 0:3f9dbf1e2cb0 217 // throw std::bad_alloc();
hideakitai 0:3f9dbf1e2cb0 218 }
hideakitai 0:3f9dbf1e2cb0 219
hideakitai 0:3f9dbf1e2cb0 220 to->m_array = nvec;
hideakitai 0:3f9dbf1e2cb0 221 to->m_end = nvec + nnext;
hideakitai 0:3f9dbf1e2cb0 222 to->m_tail = nvec + tosize;
hideakitai 0:3f9dbf1e2cb0 223 }
hideakitai 0:3f9dbf1e2cb0 224
hideakitai 0:3f9dbf1e2cb0 225 std::memcpy(to->m_tail, m_array, sizeof(iovec)*nused);
hideakitai 0:3f9dbf1e2cb0 226
hideakitai 0:3f9dbf1e2cb0 227 to->m_tail += nused;
hideakitai 0:3f9dbf1e2cb0 228 m_tail = m_array;
hideakitai 0:3f9dbf1e2cb0 229
hideakitai 0:3f9dbf1e2cb0 230
hideakitai 0:3f9dbf1e2cb0 231 inner_buffer* const ib = &m_inner_buffer;
hideakitai 0:3f9dbf1e2cb0 232 inner_buffer* const toib = &to->m_inner_buffer;
hideakitai 0:3f9dbf1e2cb0 233
hideakitai 0:3f9dbf1e2cb0 234 chunk* last = ib->head;
hideakitai 0:3f9dbf1e2cb0 235 while(last->next) {
hideakitai 0:3f9dbf1e2cb0 236 last = last->next;
hideakitai 0:3f9dbf1e2cb0 237 }
hideakitai 0:3f9dbf1e2cb0 238 last->next = toib->head;
hideakitai 0:3f9dbf1e2cb0 239 toib->head = ib->head;
hideakitai 0:3f9dbf1e2cb0 240
hideakitai 0:3f9dbf1e2cb0 241 if(toib->free < ib->free) {
hideakitai 0:3f9dbf1e2cb0 242 toib->free = ib->free;
hideakitai 0:3f9dbf1e2cb0 243 toib->ptr = ib->ptr;
hideakitai 0:3f9dbf1e2cb0 244 }
hideakitai 0:3f9dbf1e2cb0 245
hideakitai 0:3f9dbf1e2cb0 246 ib->head = empty;
hideakitai 0:3f9dbf1e2cb0 247 ib->free = sz;
hideakitai 0:3f9dbf1e2cb0 248 ib->ptr = reinterpret_cast<char*>(empty) + sizeof(chunk);
hideakitai 0:3f9dbf1e2cb0 249
hideakitai 0:3f9dbf1e2cb0 250 }
hideakitai 0:3f9dbf1e2cb0 251
hideakitai 0:3f9dbf1e2cb0 252 void clear()
hideakitai 0:3f9dbf1e2cb0 253 {
hideakitai 0:3f9dbf1e2cb0 254 chunk* c = m_inner_buffer.head->next;
hideakitai 0:3f9dbf1e2cb0 255 chunk* n;
hideakitai 0:3f9dbf1e2cb0 256 while(c) {
hideakitai 0:3f9dbf1e2cb0 257 n = c->next;
hideakitai 0:3f9dbf1e2cb0 258 ::free(c);
hideakitai 0:3f9dbf1e2cb0 259 c = n;
hideakitai 0:3f9dbf1e2cb0 260 }
hideakitai 0:3f9dbf1e2cb0 261
hideakitai 0:3f9dbf1e2cb0 262 inner_buffer* const ib = &m_inner_buffer;
hideakitai 0:3f9dbf1e2cb0 263 c = ib->head;
hideakitai 0:3f9dbf1e2cb0 264 c->next = nullptr;
hideakitai 0:3f9dbf1e2cb0 265 ib->free = m_chunk_size;
hideakitai 0:3f9dbf1e2cb0 266 ib->ptr = reinterpret_cast<char*>(c) + sizeof(chunk);
hideakitai 0:3f9dbf1e2cb0 267
hideakitai 0:3f9dbf1e2cb0 268 m_tail = m_array;
hideakitai 0:3f9dbf1e2cb0 269 }
hideakitai 0:3f9dbf1e2cb0 270
hideakitai 0:3f9dbf1e2cb0 271 #if defined(MSGPACK_USE_CPP03)
hideakitai 0:3f9dbf1e2cb0 272 private:
hideakitai 0:3f9dbf1e2cb0 273 vrefbuffer(const vrefbuffer&);
hideakitai 0:3f9dbf1e2cb0 274 vrefbuffer& operator=(const vrefbuffer&);
hideakitai 0:3f9dbf1e2cb0 275 #else // defined(MSGPACK_USE_CPP03)
hideakitai 0:3f9dbf1e2cb0 276 vrefbuffer(const vrefbuffer&) = delete;
hideakitai 0:3f9dbf1e2cb0 277 vrefbuffer& operator=(const vrefbuffer&) = delete;
hideakitai 0:3f9dbf1e2cb0 278 #endif // defined(MSGPACK_USE_CPP03)
hideakitai 0:3f9dbf1e2cb0 279
hideakitai 0:3f9dbf1e2cb0 280 private:
hideakitai 0:3f9dbf1e2cb0 281 iovec* m_tail;
hideakitai 0:3f9dbf1e2cb0 282 iovec* m_end;
hideakitai 0:3f9dbf1e2cb0 283 iovec* m_array;
hideakitai 0:3f9dbf1e2cb0 284
hideakitai 0:3f9dbf1e2cb0 285 size_t m_ref_size;
hideakitai 0:3f9dbf1e2cb0 286 size_t m_chunk_size;
hideakitai 0:3f9dbf1e2cb0 287
hideakitai 0:3f9dbf1e2cb0 288 inner_buffer m_inner_buffer;
hideakitai 0:3f9dbf1e2cb0 289
hideakitai 0:3f9dbf1e2cb0 290 };
hideakitai 0:3f9dbf1e2cb0 291
hideakitai 0:3f9dbf1e2cb0 292 /// @cond
hideakitai 0:3f9dbf1e2cb0 293 } // MSGPACK_API_VERSION_NAMESPACE(v1)
hideakitai 0:3f9dbf1e2cb0 294 /// @endcond
hideakitai 0:3f9dbf1e2cb0 295
hideakitai 0:3f9dbf1e2cb0 296 } // namespace msgpack
hideakitai 0:3f9dbf1e2cb0 297
hideakitai 0:3f9dbf1e2cb0 298 #endif /* msgpack/vrefbuffer.hpp */