| /* |
| Licensed to the Apache Software Foundation (ASF) under one |
| or more contributor license agreements. See the NOTICE file |
| distributed with this work for additional information |
| regarding copyright ownership. The ASF licenses this file |
| to you under the Apache License, Version 2.0 (the |
| "License"); you may not use this file except in compliance |
| with the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| */ |
| |
| #include "abstract_data.hpp" |
| |
| #include "collection.hpp" |
| #include "constants.hpp" |
| #include "request.hpp" |
| #include "tuple.hpp" |
| #include "user_type_value.hpp" |
| |
| using namespace datastax::internal::core; |
| |
| CassError AbstractData::set(size_t index, CassNull value) { |
| CASS_CHECK_INDEX_AND_TYPE(index, value); |
| elements_[index] = Element(value); |
| return CASS_OK; |
| } |
| |
| CassError AbstractData::set(size_t index, const Collection* value) { |
| CASS_CHECK_INDEX_AND_TYPE(index, value); |
| if (value->type() == CASS_COLLECTION_TYPE_MAP && value->items().size() % 2 != 0) { |
| return CASS_ERROR_LIB_INVALID_ITEM_COUNT; |
| } |
| elements_[index] = value; |
| return CASS_OK; |
| } |
| |
| CassError AbstractData::set(size_t index, const Tuple* value) { |
| CASS_CHECK_INDEX_AND_TYPE(index, value); |
| elements_[index] = value->encode_with_length(); |
| return CASS_OK; |
| } |
| |
| CassError AbstractData::set(size_t index, const UserTypeValue* value) { |
| CASS_CHECK_INDEX_AND_TYPE(index, value); |
| elements_[index] = value->encode_with_length(); |
| return CASS_OK; |
| } |
| |
| Buffer AbstractData::encode() const { |
| Buffer buf(get_buffers_size()); |
| encode_buffers(0, &buf); |
| return buf; |
| } |
| |
| Buffer AbstractData::encode_with_length() const { |
| size_t buffers_size = get_buffers_size(); |
| Buffer buf(sizeof(int32_t) + buffers_size); |
| |
| size_t pos = buf.encode_int32(0, buffers_size); |
| encode_buffers(pos, &buf); |
| |
| return buf; |
| } |
| |
| size_t AbstractData::get_buffers_size() const { |
| size_t size = 0; |
| for (ElementVec::const_iterator i = elements_.begin(), end = elements_.end(); i != end; ++i) { |
| if (!i->is_unset()) { |
| size += i->get_size(); |
| } else { |
| size += sizeof(int32_t); // null |
| } |
| } |
| return size; |
| } |
| |
| void AbstractData::encode_buffers(size_t pos, Buffer* buf) const { |
| for (ElementVec::const_iterator i = elements_.begin(), end = elements_.end(); i != end; ++i) { |
| if (!i->is_unset()) { |
| pos = i->copy_buffer(pos, buf); |
| } else { |
| pos = buf->encode_int32(pos, -1); // null |
| } |
| } |
| } |
| |
| size_t AbstractData::Element::get_size() const { |
| if (type_ == COLLECTION) { |
| return collection_->get_size_with_length(); |
| } else { |
| assert(type_ == BUFFER || type_ == NUL); |
| return buf_.size(); |
| } |
| } |
| |
| size_t AbstractData::Element::copy_buffer(size_t pos, Buffer* buf) const { |
| if (type_ == COLLECTION) { |
| Buffer encoded(collection_->encode_with_length()); |
| return buf->copy(pos, encoded.data(), encoded.size()); |
| } else { |
| assert(type_ == BUFFER || type_ == NUL); |
| return buf->copy(pos, buf_.data(), buf_.size()); |
| } |
| } |
| |
| Buffer AbstractData::Element::get_buffer() const { |
| if (type_ == COLLECTION) { |
| return collection_->encode_with_length(); |
| } else { |
| assert(type_ == BUFFER || type_ == NUL); |
| return buf_; |
| } |
| } |