1 /*
2   Copyright (c) DataStax, Inc.
3 
4   Licensed under the Apache License, Version 2.0 (the "License");
5   you may not use this file except in compliance with the License.
6   You may obtain a copy of the License at
7 
8   http://www.apache.org/licenses/LICENSE-2.0
9 
10   Unless required by applicable law or agreed to in writing, software
11   distributed under the License is distributed on an "AS IS" BASIS,
12   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   See the License for the specific language governing permissions and
14   limitations under the License.
15 */
16 
17 #ifndef DATASTAX_INTERNAL_BUFFER_HPP
18 #define DATASTAX_INTERNAL_BUFFER_HPP
19 
20 #include "ref_counted.hpp"
21 #include "serialization.hpp"
22 #include "vector.hpp"
23 
24 #include <uv.h>
25 
26 namespace datastax { namespace internal { namespace core {
27 
28 class Buffer {
29 public:
Buffer()30   Buffer()
31       : size_(0) {}
32 
Buffer(const char * data,size_t size)33   Buffer(const char* data, size_t size)
34       : size_(size) {
35     if (size > FIXED_BUFFER_SIZE) {
36       RefBuffer* buffer = RefBuffer::create(size);
37       buffer->inc_ref();
38       memcpy(buffer->data(), data, size);
39       data_.buffer = buffer;
40     } else if (size > 0) {
41       memcpy(data_.fixed, data, size);
42     }
43   }
44 
Buffer(size_t size)45   explicit Buffer(size_t size)
46       : size_(size) {
47     if (size > FIXED_BUFFER_SIZE) {
48       RefBuffer* buffer = RefBuffer::create(size);
49       buffer->inc_ref();
50       data_.buffer = buffer;
51     }
52   }
53 
Buffer(const Buffer & buf)54   Buffer(const Buffer& buf)
55       : size_(0) {
56     copy(buf);
57   }
58 
operator =(const Buffer & buf)59   Buffer& operator=(const Buffer& buf) {
60     copy(buf);
61     return *this;
62   }
63 
~Buffer()64   ~Buffer() {
65     if (size_ > FIXED_BUFFER_SIZE) {
66       data_.buffer->dec_ref();
67     }
68   }
69 
encode_byte(size_t offset,uint8_t value)70   size_t encode_byte(size_t offset, uint8_t value) {
71     assert(offset + sizeof(uint8_t) <= static_cast<size_t>(size_));
72     internal::encode_byte(data() + offset, value);
73     return offset + sizeof(uint8_t);
74   }
75 
encode_int8(size_t offset,int8_t value)76   size_t encode_int8(size_t offset, int8_t value) {
77     assert(offset + sizeof(int8_t) <= static_cast<size_t>(size_));
78     internal::encode_int8(data() + offset, value);
79     return offset + sizeof(int8_t);
80   }
81 
encode_int16(size_t offset,int16_t value)82   size_t encode_int16(size_t offset, int16_t value) {
83     assert(offset + sizeof(int16_t) <= static_cast<size_t>(size_));
84     internal::encode_int16(data() + offset, value);
85     return offset + sizeof(int16_t);
86   }
87 
encode_uint16(size_t offset,uint16_t value)88   size_t encode_uint16(size_t offset, uint16_t value) {
89     assert(offset + sizeof(uint16_t) <= static_cast<size_t>(size_));
90     internal::encode_uint16(data() + offset, value);
91     return offset + sizeof(uint16_t);
92   }
93 
encode_int32(size_t offset,int32_t value)94   size_t encode_int32(size_t offset, int32_t value) {
95     assert(offset + sizeof(int32_t) <= static_cast<size_t>(size_));
96     internal::encode_int32(data() + offset, value);
97     return offset + sizeof(int32_t);
98   }
99 
encode_uint32(size_t offset,uint32_t value)100   size_t encode_uint32(size_t offset, uint32_t value) {
101     assert(offset + sizeof(uint32_t) <= static_cast<size_t>(size_));
102     internal::encode_uint32(data() + offset, value);
103     return offset + sizeof(uint32_t);
104   }
105 
encode_int64(size_t offset,int64_t value)106   size_t encode_int64(size_t offset, int64_t value) {
107     assert(offset + sizeof(int64_t) <= static_cast<size_t>(size_));
108     internal::encode_int64(data() + offset, value);
109     return offset + sizeof(int64_t);
110   }
111 
encode_float(size_t offset,float value)112   size_t encode_float(size_t offset, float value) {
113     assert(offset + sizeof(float) <= static_cast<size_t>(size_));
114     internal::encode_float(data() + offset, value);
115     return offset + sizeof(float);
116   }
117 
encode_double(size_t offset,double value)118   size_t encode_double(size_t offset, double value) {
119     assert(offset + sizeof(double) <= static_cast<size_t>(size_));
120     internal::encode_double(data() + offset, value);
121     return offset + sizeof(double);
122   }
123 
encode_long_string(size_t offset,const char * value,int32_t size)124   size_t encode_long_string(size_t offset, const char* value, int32_t size) {
125     size_t pos = encode_int32(offset, size);
126     return copy(pos, value, size);
127   }
128 
encode_bytes(size_t offset,const char * value,int32_t size)129   size_t encode_bytes(size_t offset, const char* value, int32_t size) {
130     size_t pos = encode_int32(offset, size);
131     if (size > 0) {
132       return copy(pos, value, size);
133     }
134     return pos;
135   }
136 
encode_string(size_t offset,const char * value,uint16_t size)137   size_t encode_string(size_t offset, const char* value, uint16_t size) {
138     size_t pos = encode_uint16(offset, size);
139     return copy(pos, value, size);
140   }
141 
encode_string_list(size_t offset,const Vector<String> & value)142   size_t encode_string_list(size_t offset, const Vector<String>& value) {
143     size_t pos = encode_uint16(offset, static_cast<uint16_t>(value.size()));
144     for (Vector<String>::const_iterator it = value.begin(), end = value.end(); it != end; ++it) {
145       pos = encode_string(pos, it->data(), static_cast<uint16_t>(it->size()));
146     }
147     return pos;
148   }
149 
encode_string_map(size_t offset,const Map<String,String> & value)150   size_t encode_string_map(size_t offset, const Map<String, String>& value) {
151     size_t pos = encode_uint16(offset, static_cast<uint16_t>(value.size()));
152     for (Map<String, String>::const_iterator it = value.begin(); it != value.end(); ++it) {
153       pos = encode_string(pos, it->first.c_str(), static_cast<uint16_t>(it->first.size()));
154       pos = encode_string(pos, it->second.c_str(), static_cast<uint16_t>(it->second.size()));
155     }
156     return pos;
157   }
158 
encode_uuid(size_t offset,CassUuid value)159   size_t encode_uuid(size_t offset, CassUuid value) {
160     assert(offset + sizeof(CassUuid) <= static_cast<size_t>(size_));
161     internal::encode_uuid(data() + offset, value);
162     return offset + sizeof(CassUuid);
163   }
164 
copy(size_t offset,const char * value,size_t size)165   size_t copy(size_t offset, const char* value, size_t size) {
166     assert(offset + size <= static_cast<size_t>(size_));
167     memcpy(data() + offset, value, size);
168     return offset + size;
169   }
170 
copy(size_t offset,const uint8_t * source,size_t size)171   size_t copy(size_t offset, const uint8_t* source, size_t size) {
172     return copy(offset, reinterpret_cast<const char*>(source), size);
173   }
174 
data()175   char* data() {
176     return size_ > FIXED_BUFFER_SIZE ? static_cast<RefBuffer*>(data_.buffer)->data() : data_.fixed;
177   }
178 
data() const179   const char* data() const {
180     return size_ > FIXED_BUFFER_SIZE ? static_cast<RefBuffer*>(data_.buffer)->data() : data_.fixed;
181   }
182 
size() const183   size_t size() const { return size_; }
184 
185 private:
186   // Enough space to avoid extra allocations for most of the basic types
187   static const size_t FIXED_BUFFER_SIZE = 16;
188 
189 private:
copy(const Buffer & buf)190   void copy(const Buffer& buf) {
191     RefBuffer* temp = data_.buffer;
192 
193     if (buf.size_ > FIXED_BUFFER_SIZE) {
194       buf.data_.buffer->inc_ref();
195       data_.buffer = buf.data_.buffer;
196     } else if (buf.size_ > 0) {
197       memcpy(data_.fixed, buf.data_.fixed, buf.size_);
198     }
199 
200     if (size_ > FIXED_BUFFER_SIZE) {
201       temp->dec_ref();
202     }
203 
204     size_ = buf.size_;
205   }
206 
207   union Data {
208     char fixed[FIXED_BUFFER_SIZE];
209     RefBuffer* buffer;
210 
Data()211     Data()
212         : buffer(NULL) {}
213   } data_;
214 
215   size_t size_;
216 };
217 
218 typedef Vector<Buffer> BufferVec;
219 
220 }}} // namespace datastax::internal::core
221 
222 #endif
223