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