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