| /* |
| 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 "encode.hpp" |
| #include "serialization.hpp" |
| #include "utils.hpp" |
| |
| namespace datastax { namespace internal { namespace core { |
| |
| static char* encode_vint(char* output, uint64_t value, size_t value_size) { |
| if (value_size == 1) { |
| // This is just a one byte value; write it and get out. |
| *output = static_cast<char>(value); |
| return output + 1; |
| } |
| |
| // Write the bytes of zigzag value to the output array with most significant byte |
| // in first byte of buffer, and so on. |
| for (int j = value_size - 1; j >= 0; --j) { |
| *(output + j) = value & 0xff; |
| value >>= 8; |
| } |
| |
| // Now mix in the size of the vint into the first byte of the buffer, |
| // setting "value_size-1" higher order bits. |
| *output |= ~(0xff >> (value_size - 1)); |
| |
| // We're done with value_size bytes |
| return output + value_size; |
| } |
| |
| static Buffer encode_internal(CassDuration value, bool with_length) { |
| // Each duration attribute needs to be converted to zigzag form. Use an array to make it |
| // easy to do the same encoding ops on all three values. |
| uint64_t zigzag_values[3]; |
| |
| // We need vint sizes for each attribute. |
| size_t vint_sizes[3]; |
| |
| zigzag_values[0] = encode_zig_zag(value.months); |
| zigzag_values[1] = encode_zig_zag(value.days); |
| zigzag_values[2] = encode_zig_zag(value.nanos); |
| |
| // We also need the total size of all three vint's. |
| size_t data_size = 0; |
| for (int i = 0; i < 3; ++i) { |
| vint_sizes[i] = vint_size(zigzag_values[i]); |
| data_size += vint_sizes[i]; |
| } |
| |
| // Allocate our data buffer and then start populating it. If we're including the length, |
| // allocate extra space for that. |
| Buffer buf(with_length ? sizeof(int32_t) + data_size : data_size); |
| |
| // Write the length if with_length is set; this means subsequent data is written afterwards |
| // in buf. Use pos to set our next write position properly regardless of with_length. Since we |
| // don't write sequentially to the buffer (we jump around a bit) the easiest thing to do is grab |
| // a pointer to the underlying data buffer and manipulate it. |
| size_t pos = with_length ? buf.encode_int32(0, data_size) : 0; |
| char* cur_byte = buf.data() + pos; |
| |
| for (int i = 0; i < 3; ++i) { |
| cur_byte = encode_vint(cur_byte, zigzag_values[i], vint_sizes[i]); |
| } |
| return buf; |
| } |
| |
| Buffer encode(CassDuration value) { return encode_internal(value, false); } |
| |
| Buffer encode_with_length(CassDuration value) { return encode_internal(value, true); } |
| |
| }}} // namespace datastax::internal::core |