1// 2// MessagePack for C++ simple buffer implementation 3// 4// Copyright (C) 2008-2013 FURUHASHI Sadayuki and KONDO Takatoshi 5// 6// Distributed under the Boost Software License, Version 1.0. 7// (See accompanying file LICENSE_1_0.txt or copy at 8// http://www.boost.org/LICENSE_1_0.txt) 9// 10#ifndef MSGPACK_SBUFFER_HPP 11#define MSGPACK_SBUFFER_HPP 12 13#include "msgpack/versioning.hpp" 14 15#include <stdexcept> 16 17#ifndef MSGPACK_SBUFFER_INIT_SIZE 18#define MSGPACK_SBUFFER_INIT_SIZE 8192 19#endif 20 21namespace msgpack { 22 23/// @cond 24MSGPACK_API_VERSION_NAMESPACE(v1) { 25/// @endcond 26 27class sbuffer { 28public: 29 sbuffer(size_t initsz = MSGPACK_SBUFFER_INIT_SIZE):m_size(0), m_alloc(initsz) 30 { 31 if(initsz == 0) { 32 m_data = nullptr; 33 } else { 34 m_data = (char*)::malloc(initsz); 35 if(!m_data) { 36 throw std::bad_alloc(); 37 } 38 } 39 } 40 41 ~sbuffer() 42 { 43 ::free(m_data); 44 } 45 46#if !defined(MSGPACK_USE_CPP03) 47 sbuffer(const sbuffer&) = delete; 48 sbuffer& operator=(const sbuffer&) = delete; 49 50 sbuffer(sbuffer&& other) : 51 m_size(other.m_size), m_data(other.m_data), m_alloc(other.m_alloc) 52 { 53 other.m_size = other.m_alloc = 0; 54 other.m_data = nullptr; 55 } 56 57 sbuffer& operator=(sbuffer&& other) 58 { 59 ::free(m_data); 60 61 m_size = other.m_size; 62 m_alloc = other.m_alloc; 63 m_data = other.m_data; 64 65 other.m_size = other.m_alloc = 0; 66 other.m_data = nullptr; 67 68 return *this; 69 } 70#endif // !defined(MSGPACK_USE_CPP03) 71 72 void write(const char* buf, size_t len) 73 { 74 if(m_alloc - m_size < len) { 75 expand_buffer(len); 76 } 77 std::memcpy(m_data + m_size, buf, len); 78 m_size += len; 79 } 80 81 char* data() 82 { 83 return m_data; 84 } 85 86 const char* data() const 87 { 88 return m_data; 89 } 90 91 size_t size() const 92 { 93 return m_size; 94 } 95 96 char* release() 97 { 98 char* tmp = m_data; 99 m_size = 0; 100 m_data = nullptr; 101 m_alloc = 0; 102 return tmp; 103 } 104 105 void clear() 106 { 107 m_size = 0; 108 } 109 110private: 111 void expand_buffer(size_t len) 112 { 113 size_t nsize = (m_alloc > 0) ? 114 m_alloc * 2 : MSGPACK_SBUFFER_INIT_SIZE; 115 116 while(nsize < m_size + len) { 117 size_t tmp_nsize = nsize * 2; 118 if (tmp_nsize <= nsize) { 119 nsize = m_size + len; 120 break; 121 } 122 nsize = tmp_nsize; 123 } 124 125 void* tmp = ::realloc(m_data, nsize); 126 if(!tmp) { 127 throw std::bad_alloc(); 128 } 129 130 m_data = static_cast<char*>(tmp); 131 m_alloc = nsize; 132 } 133 134#if defined(MSGPACK_USE_CPP03) 135private: 136 sbuffer(const sbuffer&); 137 sbuffer& operator=(const sbuffer&); 138#endif // defined(MSGPACK_USE_CPP03) 139 140private: 141 size_t m_size; 142 char* m_data; 143 size_t m_alloc; 144}; 145 146/// @cond 147} // MSGPACK_API_VERSION_NAMESPACE(v1) 148/// @endcond 149 150} // namespace msgpack 151 152#endif /* msgpack/sbuffer.hpp */ 153